How to display if a field exists in other table? - sql-server

I want to show/display if the product is found each transaction.
tblProducts
ID PRODCODE PRODDESC
1 PFX-321 MILK CHOCO
2 PDF-875 COFFEE JELLY
3 PWA-718 MILK SHAKE
tblTransactions
TCODE PRODCODE
BMX2213391 PFX-321
BMX2213391 PDF-875
PDFSD92851 PDF-875
I want the results to display like this
TCODE PRODCODE FOUND
BMX2213391 PFX-321 YES
BMX2213391 PDF-875 YES
BMX2213391 PWA-718 NO
PDFSD92851 PFX-321 NO
PDFSD92851 PDF-875 YES
PDFSD92851 PWA-718 NO
I tried, INNER JOIN, FULL OUTER JOIN, LEFT JOIN and RIGHT JOIN but I don't get the exact data I need.
Here are the queries I test.
SELECT * FROM tblProducts a INNER JOIN tblTransactions b ON a.PRODCODE = b.PRODCODE
SELECT * FROM tblProducts a FULL OUTER JOIN tblTransactions b ON a.PRODCODE = b.PRODCODE
SELECT * FROM tblProducts a LEFT JOIN tblTransactions b ON a.PRODCODE = b.PRODCODE
SELECT * FROM tblProducts a RIGHT JOIN tblTransactions b ON a.PRODCODE = b.PRODCODE

I'm pretty sure this works - SQLFiddle here: http://sqlfiddle.com/#!3/65eb1/23
WITH AllVals AS
(SELECT a.PRODCODE, b.TCODE
FROM tblProducts a
CROSS JOIN tblTransactions b)
SELECT DISTINCT c.PRODCODE,
c.TCODE,
CASE WHEN d.PRODCODE IS NULL THEN 'NO' ELSE 'YES' END AS FOUND
FROM AllVals c
LEFT OUTER JOIN tblTransactions d
ON c.PRODCODE = d.PRODCODE
AND c.TCODE = d.TCODE

http://sqlfiddle.com/#!3/65eb1/24
select DT.TCODE, DT.PRODCODE, case when (Tr2.TCODE IS null and Tr2.PRODCODE IS null) then 'No' else 'Yes' END as FOUND
from tblTransactions Tr2 right join
(
select distinct Tr.TCODE, p.PRODCODE
from tblProducts p cross join tblTransactions Tr
) DT
on DT.PRODCODE = Tr2.PRODCODE and DT.TCODE = Tr2.TCODE;

Related

SQL Server 2005 Select Data From Table1 and Table2 but if Table2 column1 value is null Select Data From Table3

My Query IS
SELECT TblPharmacyBillingDetails.UPBNo, TblMasterBillingData.IPDNo, InPatRegistration.PatTitle+PatientName, TblPharmacyBillingDetails.InvoiceNo, TblPharmacyBillingDetails.InvoiceDateTime, TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN InPatRegistration ON TblMasterBillingData.IPDNo = InPatRegistration.IPDNo
but if TblMasterBillingData.IPDNo value is NULL select Data From TblMasterBillingData.OPDNo and
INNER JOIN OutPatRegistration ON TblMasterBillingData.OPDNo = OutPatRegistration.IPDNo
Method #1: Using UNION
SELECT * FROm
(
SELECT TblPharmacyBillingDetails.UPBNo,
TblMasterBillingData.IPDNo,
InPatRegistration.PatTitle+PatientName,
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN InPatRegistration ON TblMasterBillingData.IPDNo = InPatRegistration.IPDNo
WHERE TblMasterBillingData.IPDNo IS NOT NULL
UNION ALL
SELECT TblPharmacyBillingDetails.UPBNo,
TblMasterBillingData.OPDNo,
OutPatRegistration .PatTitle + PatientName,
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN OutPatRegistration ON TblMasterBillingData.OPDNo = OutPatRegistration.OPDNo
WHERE TblMasterBillingData.OPDNo IS NOT NULL
)Tmp
ORDER BY TblPharmacyBillingDetails.UPBNo
Method #2 Using ISNULL and LEFT JOIN
SELECT TblPharmacyBillingDetails.UPBNo,
ISNULL(TblMasterBillingData.IPDNo,TblMasterBillingData.OPDNo),
ISNULL(IP.PatTitle + IP.PatientName, OP.PatTitle + OP.PatientName),
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
LEFT JOIN InPatRegistration IP ON TblMasterBillingData.IPDNo = IP.IPDNo
LEFT JOIN outPatRegistration OP ON TblMasterBillingData.OPDNo = OP.OPDNo
ORDER BY TblPharmacyBillingDetails.UPBNo
You can write either case statement or ISNULL() function as shown below in the demo query.
SELECT
Orders.OrderID,
Case when Customers1.CustomerName is null then Customers2.CustomerName else Customers1.CustomerName
end as CustomerName, --way 1
ISNULL(Customers1.CustomerName, Customers2.CustomerName) as Customer, --way 2
Orders.OrderDate
FROM Orders
INNER JOIN Customers1 ON Orders.CustomerID = Customers1.CustomerID
INNER JOIN Customers2 ON Orders.CustomerID = Customers2.CustomerID
-- where your condition here
-- order by your column name
You can also check whether data is available or not in the table and join the table accordingly using if exists as shown below.
if exists(select 1 from tablename where columnname = <your values>)

SQL Server : left join - check for right table column value is null

I have a query as follows:
select --this select should always give me 1 record
tbl1.Id, tbl1.Name, tbl1.Address, tbl2.relNo,
CASE WHEN tbl3.Comments IS NOT NULL THEN 1 ELSE 0 END AS 'Required'
from
table1 tbl1
inner join
table2 tbl2 on tbl2.Id = tbl1.Id
left join -- This left join table gives me 5 records for one instance
(select
R.Id, C.Comments
from
tblC C
inner join
tblR R on R.Id = C.id) tbl3 on tbl3.Id = tbl2.Id
I want to write a CASE statement on the rows my left join is giving to check for null value as above and my final select query always return only 1 row. Is there a way to check if all five Comments Column values from my left join be checked for NULLs in the above query?
I would take a shortcut an use a COUNT() OVER PARTITION
CASE WHEN COUNT(*) OVER (PARTITION BY tbl3.Id) =0 THEN 0 ELSE 1 END AS 'Required'
You would have to DISTINCT your output above. Another option would be to GROUP BY and filter in the HAVING clause.
select --this select should always give me 1 record
tbl1.Id, tbl1.Name, tbl1.Address, tbl2.relNo
From table1 tbl1
inner join table2 tbl2 on tbl2.Id = tbl1.Id
left join (-- This left join table gives me 5 records for one instance
SELECT R.Id,
C.Comments
FROM tblC C
INNER JOIN tblR R on R.Id = C.id
) tbl3 on tbl3.Id = tbl2.Id
GROUP BY
Id, Name, Address, relNo
HAVING
COUNT(*) = 5
Is this what you're looking for?
(CASE WHEN (select count(tbl3.id) FROM tbl3 WHERE tbl3.Comments IS NULL) then 1 else 0 end) as 'RequiredVal'
select --this select should always give me 1 record
tbl1.Id, tbl1.Name, tbl1.Address, tbl2.relNo,
CASE WHEN tbl3.Comments IS NOT NULL THEN 1 ELSE 0 END AS 'Required'
, (CASE WHEN (select count(tbl3.id) FROM tbl3 WHERE tbl3.Comments IS NULL) then 1 else 0 end) as 'RequiredVal'
From table1 tbl1
inner join table2 tbl2 on tbl2.Id = tbl1.Id
left join (-- This left join table gives me 5 records for one instance
SELECT R.Id,
C.Comments
FROM tblC C
INNER JOIN tblR R on R.Id = C.id
) tbl3 on tbl3.Id = tbl2.Id

Is it possible to Replace CTE and SELECT with just single sql query (dependent results)

I have the following query. Given productid as input (2,4,5) i want to get keyid associate with that list. Then i want to get all products associated with that keyids.
For example:
suppose i am passing productid as 2,4,5 as input to my sproc, i will get keyids as 22,34,35,38 (CTE result). This keys are mapped to the input productlist. Based on this keys (CTE result) i want all the products associated to this keys. Say the keyid = 22 will now have product names with product id as 2,4,5,89 & keyid = 34 will now have products associated to 2,4,5,23,45 etc.
I came up with the following solution for the above problem. I am just hoping whether we could somehow improve this solution or do this job in single query as two tables are getting repeated.
WITH GetKey_CTE
AS
(
SELECT k.id, some other select statements
FROM KeyDim k
INNER JOIN KeyData kd on kd.id = k.id
INNER JOIN KeyProductMapping kpm on kpm.id = k.id and kpm.mkey = k.mkey
INNER JOIN Products p on p.productid = kpm.productid
and p.productid IN (2,4,5)
LEFT JOIN some more joins
WHERE clause conditions
)
SELECT cte.id as keyid, pn.productname, some other columns
FROM GetKey_CTE cte
INNER JOIN KeyProductMapping kpm on cte.id = kpm.id
INNER JOIN Products pn on pn.productid = kpm.productid
ORDER BY cte.id
Dataset Example for products and productkeymapping tables :
For Products table:
productid name
1 car
2 bike
3 plane
4 bus
5 train
45 cycle
ProductKeyMapping table
productid keyid
1 23
2 987
45 23
1 56
say input productid is 1, then final result should be:
keyid productid name
23 1 car
23 45 cycle
56 1 car
just looking at the data and that simple example
select pm2.*, product.name
from productmapping pm1
join productmapping pm2
on pm2.keyid = pm1.keyid
and pm1.productid in (1)
join product
on product.id = pm2.productid
declare #product table(id int, name varchar(20));
declare #map table(productid int, keyid int);
insert into #product values
(1, 'car'),
(2, 'bike'),
(3, 'plane'),
(4, 'bus'),
(5, 'train'),
(45, 'cycle');
insert into #map values
(1, '23'),
(2, '987'),
(45, '23'),
(1, '56');
select pm2.*, p.name
from #map pm1
join #map pm2
on pm2.keyid = pm1.keyid
and pm1.productid in (1)
join #product p
on p.id = pm2.productid
order by pm2.keyid;
you can also done by using sub query
SELECT * FROM KeyProductMapping km
INNER JOIN
(
SELECT k.id, some other select statements
FROM KeyDim k
INNER JOIN KeyData kd ON kd.id = k.id
INNER JOIN KeyProductMapping kpm ON kpm.id = k.id AND kpm.mkey = k.mkey
INNER JOIN Products p ON p.productid = kpm.productid
AND p.productid IN (2,4,5)
LEFT JOIN some more joins
WHERE clause conditions) AS p ON p.id = km.id
INNER JOIN Products pn ON p.productid = km.productid
ORDER BY cte.id
SELECT cte.id as keyid, pn.productname, some other columns
FROM ( SELECT k.id, some other select statements
FROM KeyDim k
JOIN KeyData kd
on kd.id = k.id
JOIN KeyProductMapping kpm
on kpm.id = k.id
and kpm.mkey = k.mkey
JOIN Products p
on p.productid = kpm.productid
and p.productid IN (2,4,5)
LEFT JOIN some more joins
WHERE clause conditions
) CTE
JOIN KeyProductMapping kpm
on cte.id = kpm.id
JOIN Products pn
on pn.productid = kpm.productid
ORDER BY cte.id
Above you you query with the CTE in line (a subquery)
A lot of stuff does not make sense to me
JOIN KeyProductMapping kpm
on kpm.id = k.id
and kpm.mkey = k.mkey
JOIN Products p
on p.productid = kpm.productid
and p.productid IN (2,4,5)
is the same as
JOIN KeyProductMapping kpm
on kpm.id = k.id
and kpm.mkey = k.mkey
and p.productid IN (2,4,5)
unless product does not have those values
why
SELECT k.id, some other select statements
FROM KeyDim k
JOIN KeyData kd
on kd.id = k.id
same as
SELECT kd.id -- move this to main select, some other select statements
FROM KeyData kd
why?
LEFT JOIN some more joins
move that to main statement
You can replace the CTE with an inline view like below but note sure why you are duplicating the JOINS again. Can you post some sample data along with your desired result to look further.
SELECT cte.id AS keyid, pn.productname, some other columns
FROM (
SELECT k.id, some other select statements
FROM KeyDim k
INNER JOIN KeyData kd ON kd.id = k.id
INNER JOIN KeyProductMapping kpm ON kpm.id = k.id AND kpm.mkey = k.mkey
INNER JOIN Products p ON p.productid = kpm.productid
AND p.productid IN (2,4,5)
LEFT JOIN some more joins
WHERE clause conditions ) cte
INNER JOIN KeyProductMapping kpm ON cte.id = kpm.id
INNER JOIN Products pn ON cte.productid = kpm.productid
ORDER BY cte.id

SQL Server Nested Query Performance

I need some help writing this query for SQL Server. The nested part makes this query take almost a minute to run on 27,000 records. I think it needs a temp table, but I have not done this before. Can someone give me an idea how I might do this?
SELECT
r.ID,
r.CloseDate,
r.RepairOrderStatus 'Repair Status',
p.PartNumber ModInPN,
p.PartDescription ModInDesc,
pr.RMANumber,
c.FullName OpsTech,
(SELECT COUNT (*)
FROM dbo.TestPartsReplaced tpr
WHERE tpr.RepairID = r.ID) Qty
FROM dbo.RepairTicket r LEFT JOIN dbo.Parts p ON r.ModuleInPartID = p.ID
LEFT JOIN dbo.PartReturn pr ON r.PartReturnID = pr.ID
LEFT JOIN dbo.Contact c ON c.ID = r.ContactTechID
Try this....
SELECT
r.ID,
r.CloseDate,
r.RepairOrderStatus 'Repair Status',
p.PartNumber ModInPN,
p.PartDescription ModInDesc,
pr.RMANumber,
c.FullName OpsTech,
Qty.[Count] AS Quantity
FROM dbo.RepairTicket r LEFT JOIN dbo.Parts p ON r.ModuleInPartID = p.ID
LEFT JOIN dbo.PartReturn pr ON r.PartReturnID = pr.ID
LEFT JOIN dbo.Contact c ON c.ID = r.ContactTechID
LEFT JOIN (SELECT RepairID , COUNT (*) AS [Count]
FROM dbo.TestPartsReplaced
GROUP BY RepairID) Qty ON Qty.RepairID = r.ID

multiple count in a sql query

i need a report from a database where i need the final result like
Number of Male, Number of Female, showing against city and finally against State.
I started off with something like.
SELECT p.StateName, d.CityName,
count(api.Gender) as Gender
FROM dbo.Application_Personal_information as api INNER JOIN
dbo.state as p ON api.State = p.ID INNER JOIN
dbo.City as d ON api.City= d.ID
group by p.StateName, d.CityName
when i do this
SELECT p.StateName, d.CityName,
count(api.Gender = 'Male) as Male,
count(api.Gender = 'Female) as Female,
FROM dbo.Application_Personal_information as api INNER JOIN
dbo.state as p ON api.State = p.ID INNER JOIN
dbo.City as d ON api.City= d.ID
group by p.StateName, d.CityName
it give's me error.
incorrect syntax near =.
i also tried with select statement
COUNT(select api.Gender from api where api.Gender ='Male') as Male,
But it is also not working.
...
Any idea?
SELECT
p.StateName, d.CityName,
sum(case when Gender ='Male' then 1 else 0 end ) as Male_count,
sum(case when Gender ='Female' then 1 else 0 end ) as Female_count
FROM
dbo.Application_Personal_information as api INNER JOIN
dbo.state as p ON api.State = p.ID INNER JOIN
dbo.City as d ON api.City= d.ID
group by
p.StateName, d.CityName
You could try the PIVOT function if you are using SQL Server 2005 or later:
WITH CTE AS
( SELECT p.StateName,
d.CityName,
api.Gender
FROM dbo.Application_Personal_information as api
INNER JOIN dbo.state as p
ON api.State = p.ID
INNER JOIN dbo.City as d
ON api.City= d.ID
)
SELECT *
FROM CTE
PIVOT
( COUNT(Gender)
FOR Gender IN ([Male], [Female])
) pvt

Resources