How to select distinct from union result with condition - sql-server

I want to select distinct vendor with chase if there are two vendor with status register and not register then the choosen one is vendor with status register but if only one vendor then just select it,
I'm using sql server 2017
SELECT
pv.vendor_id,pv.vendor_name,'Not Registered' as registration_status
FROM
proposal_vendor as pv
UNION
SELECT bv.vendor_id,bv.vendor_name,bv.registration_status
FROM
bidding_vendor as bv
WHERE
bv.bidding_header_id = 97
48 vendor a Register
48 vendor a Not Registered
4110 vendor b Register
4110 vendor b Not Registered
4197 vendor c Not Registered
what i'm expected is
48 vendor a Register
4110 vendor b Register
4197 vendor c Not Registered

You can get your expected output using row number and case statement. If you have two registered then you can use rank, else you can use row number if you want just one row per vendor id.
select vendor_id, vendor_name, registration_status from (
SELECT bv.vendor_id,bv.vendor_name,bv.registration_status, row_number() over (partition by bv.vendor_id order by case when registration_status = 'Register' then 1 else 2) rownum
FROM
bidding_vendor as bv) t
where t.rownum = 1

SELECT pv.vendor_id,
pv.vendor_name,
'Not Registered' as registration_status
FROM proposal_vendor as pv
WHERE NOT EXISTS(SELECT 1
FROM bidding_vendor bv
WHERE bv.vendor_id = pv.vendor_id
AND bv.bidding_header_id = 97)
UNION ALL
SELECT bv.vendor_id,
bv.vendor_name,
bv.registration_status
FROM bidding_vendor as bv
WHERE bv.bidding_header_id = 97

There are multiple possibilities here.
You can make your main query a derived table source for your results query
SELECT pv.vendor_id,
pv.vendor_name, MAX(registration_status) as registration_status
FROM (
SELECT
pv.vendor_id,pv.vendor_name,'Not Registered' as registration_status
FROM
proposal_vendor as pv
UNION
SELECT bv.vendor_id,bv.vendor_name,bv.registration_status
FROM
bidding_vendor as bv
WHERE
bv.bidding_header_id = 97
) src
You can use Outer Join logic
SELECT pv.vendor_id,
pv.vendor_name,
CASE WHEN bv.vendor_id is null
THEN 'Not '
END + 'Registered' as registration_status
FROM proposal_vendor as pv
FULL OUTER JOIN bidding_vendor as bv
ON pv.vendor_id = bv.vendor_id
WHERE pv.vendor_id = 97
OR bv.vendor_id = 97
Or you can choose another from perhaps a half dozen different techniques.

Related

Join in SQL Server when some query doesn't have results

I have a table with stock product movements (MOVSTOCKS) in two warehouses (CodAlm). For simplify the question, I will focus on a single product (with CodArt = C5):
CodArt
DescArt
CodAlm
UnidadesStock
EntranStock
SalenStock
FecDoc
TipDoc
C5
Palet
1
16
16
0
2021-12-31
IN
C5
Palet
2
0
0
0
2021-12-31
IN
C5
Palet
1
3
0
3
2022-01-11
SL
C5
Palet
1
4
0
4
2022-01-20
SL
C5
Palet
1
7
7
0
2022-02-01
EN
C5
Palet
1
6
0
6
2022-02-14
SL
C5
Palet
1
9
9
10
2022-05-01
IN
C5
Palet
2
1
1
0
2022-05-01
IN
C5
Palet
1
2
0
2
2022-06-10
SL
I need to get the stock on a certain day. For this, is necessary obtain stock quantity of the last inventory (TipDoc = IN) and add it purchases quantities (TipDoc = EN) and subtract the sales (TipDoc = SL).
I tried this query:
SELECT MV.CODART, MV.DESCART, MV.CODALM, SC.UNIDADESSTOCK + SUM(MV.ENTRANSTOCK) - SUM(MV.SALENSTOCK) as STOCK
FROM MOVSTOCKS MV
JOIN ( SELECT MV1.CODART, MV1.CODALM, MV2.FECDOC, MV1.UNIDADESSTOCK
FROM MOVSTOCKS MV1
JOIN ( SELECT CODART, CODALM, MAX(FECDOC) FECDOC
FROM MOVSTOCKS
WHERE TIPDOC = 'IN'
GROUP BY CODART, CODALM) MV2
ON MV1.CODART = MV2.CODART AND MV1.CODALM = MV2.CODALM AND MV1.FECDOC = MV2.FECDOC
WHERE MV1.TIPDOC = 'IN' ) SC
ON MV.CODART = SC.CODART AND MV.CODALM = SC.CODALM AND MV.FECDOC > SC.FECDOC
WHERE MV.CODART = 'C5' and MV.FECDOC <= '2022-06-01'
GROUP BY MV.CODART, MV.DESCART, MV.CODALM, SC.UNIDADESSTOCK
ORDER BY MV.CODART, MV.CODALM
With above data example and the query I expected to get following results:
CodArt
DescArt
CodAlm
Stock
C5
Palet
1
9
C5
Palet
2
1
The problem is that after the last inventory (2022-05-01) there have been no movements and then the join query get 0 rows because the filter MV.FECDOC <= '2022-06-01' in the WHERE doesn't get rows. I could modify the 'ON' condition in the join to MV.FECDOC >= SC.FECDOC and then get at least the inventory row, but I shouldn't do that because on inventory day there might be other previous movements that I shouldn't get for stock calculation.
Moreover, I will have the same problem if I want to get stock in a date for a product without inventory movements, because subquery 'SC' won't get rows.
Any help, please?
If you know that the inventory records exist, but the other transaction records might or might not exist afterwards, you will need to select your inventory records first and then LEFT JOIN the other transaction records.
If we only had to select one inventory record, we could start with a SELECT TOP 1 * ... ORDER BY FECDOC DESC with appropriate additional conditions. However, to get the latest inventory record for each of multiple warehouses, it get a bit more complicated. Two approaches that come to mind.
One would be to first select distinct warehouse codes (or perhaps distinct warehouse and product codes) and then CROSS APPLY a subselect to retrieve the latest inventory record for each.
The other approach would be to use the ROW_NUMBER() window function to number the inventory records by descending date (partitioned by warehouse codes and product codes) and then exclude all but row number = 1.
In either case, the next step would be to LEFT JOIN the transaction records, apply a GROUP BY, and SUM() up the results. Since SUM() returns NULL if there are no elements to sum, we need to use the ISNULL() function to assign a default value of zero.
The following two similar queries demonstrate the above approaches.
DECLARE #CODART VARCHAR(10) = 'C5'
DECLARE #AsOfDate DATETIME2 = '2022-06-01'
-- Method 1: SELECT DISTINCT followed by a cross apply
SELECT
SC.CODART, SC.DESCART, SC.CODALM,
SC.UNIDADESSTOCK + ISNULL(SUM(MV2.ENTRANSTOCK), 0) - ISNULL(SUM(MV2.SALENSTOCK), 0) as STOCK
FROM (
SELECT DISTINCT MV.CODART, MV.CODALM
FROM #MOVSTOCKS MV
WHERE MV.CODART = #CODART
) A
CROSS APPLY (
-- Most recent inventory for each selected CODART, CODALM
SELECT TOP 1 MV1.*
FROM #MOVSTOCKS MV1
WHERE MV1.CODART = A.CODART
AND MV1.CODALM = A.CODALM
AND MV1.TIPDOC = 'IN'
AND MV1.FECDOC <= #AsOfDate
ORDER BY MV1.FECDOC DESC
) SC
LEFT JOIN #MOVSTOCKS MV2
ON MV2.CODART = SC.CODART
AND MV2.CODALM = SC.CODALM
AND MV2.TIPDOC IN ('EN', 'SL')
AND MV2.FECDOC > SC.FECDOC
AND MV2.FECDOC <= #AsOfDate
GROUP BY SC.CODART, SC.DESCART, SC.CODALM, SC.UNIDADESSTOCK
ORDER BY SC.CODART, SC.CODALM
-- Method 2: Using the ROW_NUMBER() window function
SELECT
SC.CODART, SC.DESCART, SC.CODALM,
SC.UNIDADESSTOCK + ISNULL(SUM(MV2.ENTRANSTOCK), 0) - ISNULL(SUM(MV2.SALENSTOCK), 0) as STOCK
FROM (
-- Most recent inventory at or before #AsOfDate will have Recency = 1
SELECT MV1.*,
ROW_NUMBER() OVER(PARTITION BY CODART, CODALM ORDER BY FECDOC DESC) AS Recency
FROM #MOVSTOCKS MV1
WHERE MV1.FECDOC <= #AsOfDate
AND MV1.TIPDOC = 'IN'
) SC
LEFT JOIN #MOVSTOCKS MV2
ON MV2.CODART = SC.CODART
AND MV2.CODALM = SC.CODALM
AND MV2.FECDOC > SC.FECDOC
AND MV2.FECDOC <= #AsOfDate
AND MV2.TIPDOC IN ('EN', 'SL')
WHERE SC.Recency = 1
AND SC.CODART = #CODART
GROUP BY SC.CODART, SC.DESCART, SC.CODALM, SC.UNIDADESSTOCK
ORDER BY SC.CODART, SC.CODALM
Both queries above produce the desired result. See this db<>fiddle for a working demo.
*** UPDATE *** To handle cases where we might have transactions (added stock and/or sales) but no prior reference inventory, we will need to assume an initial inventory of zero and include all transactions since the beginning-of-time (start or data). This also requires making the initial SELECT DISTINCT the primary source for product and warehouse information. The CROSS APPLY becomes an OUTER APPLY (similar to a LEFT JOIN) and we need to make other adjustments to handle a possible null inventory record. That includes adjusting the date range for the transaction join.
The updated query would be something like:
SELECT
A.CODART, A.DESCART, A.CODALM,
ISNULL(SC.UNIDADESSTOCK, 0) + ISNULL(SUM(MV2.ENTRANSTOCK), 0) - ISNULL(SUM(MV2.SALENSTOCK), 0) as STOCK
, SC.UNIDADESSTOCK AS PriorInventory
, SUM(MV2.ENTRANSTOCK) AS NewStock
, SUM(MV2.SALENSTOCK) as Sales
FROM (
SELECT DISTINCT MV.CODART, MV.DESCART, MV.CODALM
FROM #MOVSTOCKS MV
WHERE MV.CODART = #CODART
) A
OUTER APPLY (
-- Most recent inventory for each selected CODART, CODALM combination
SELECT TOP 1 MV1.*
FROM #MOVSTOCKS MV1
WHERE MV1.CODART = A.CODART
AND MV1.CODALM = A.CODALM
AND MV1.TIPDOC = 'IN'
AND MV1.FECDOC <= #AsOfDate
ORDER BY MV1.FECDOC DESC
) SC
LEFT JOIN #MOVSTOCKS MV2
-- Transactions since inventory was last recorded
ON MV2.CODART = A.CODART
AND MV2.CODALM = A.CODALM
AND MV2.TIPDOC IN ('EN', 'SL') -- Alternately <> 'IN' or omitted entirely.
AND MV2.FECDOC > ISNULL(SC.FECDOC, '1900-01-01')
AND MV2.FECDOC <= #AsOfDate
GROUP BY A.CODART, A.DESCART, A.CODALM, SC.UNIDADESSTOCK
ORDER BY A.CODART, A.CODALM
See this db<>fiddle for an updated demo. For this demo, I added a new stock record for warehouse 3 and set the #AsOfDate to '2022-12-31'. I also added details to the result showing the separate initial inventory, new stock, and sales that feed the final STOCK calculation.
CODART
DESCART
CODALM
STOCK
PriorInventory
NewStock
Sales
C5
Palet
1
7
9
0
2
C5
Palet
2
1
1
null
null
C5
Palet
3
6
null
6
0
The above includes cases having inventory with transactions, inventory but no transactions, and transactions with no initial inventory.
I abandoned the ROW_NUMBER() alternate approach.

SQL Join with 2 conditions same column but different data names

I need to join 2 tables using 2 columns as identifiers,
Reference and UAP
TABLE 1
Reference
UAP
Week 1
Week 2
Table 2
Reference
UAP
Stock
Here is the problem with data on both tables in UAP column
Table 1 Table 2
UAP1 M1
UAP2 M2
UAP3 M3
UAP4 M4
UAP5 M5
UAP6 M6
UAPP PROTOS
EXT EXTR
the UAPS are the same but name is just different
I have no control over the data i'm getting, it's a IBM DB2 remote server
I tried a local table to join but i want to avoid that 'cause of the performance impact (30+ seconds)
So far my query is this
SELECT
*
FROM OPENQUERY(MACPAC,
'SELECT
P.Referencia,
P.UAP,
P.W01,
P.W02,
S.Stock
FROM AUTO.D805DATPOR.Production AS P
INNER JOIN AUTO.D805DATPOR.Stock S
ON S.Reference = S.Reference
WHERE (P.Reference Not Like ''FS%'')
ORDER BY Reference')
well of course the ideal would be
SELECT
*
FROM OPENQUERY(MACPAC,
'SELECT
P.Referencia,
P.UAP,
P.W01,
P.W02,
S.Stock
FROM AUTO.D805DATPOR.Production AS P
INNER JOIN AUTO.D805DATPOR.Stock S
ON P.Reference = S.Reference AND P.UAP = S.UAP
WHERE (P.Reference Not Like ''FS%'')
ORDER BY Reference')
but it does not work cause different names... Is there a way to make this happen without a local join table that will slow my query by several seconds?
Here is the output of these queries individually
This is the production table
This is the stock table
the output should show me the Stock on the production table by Reference and UAP
EDIT
Sorry for confusion the remote server is IBM DB2. This was an error of my coworker that said it was coming from oracle--
Cheers for correct answer from #Sergey Menshov.
SELECT
Reference,
UAP,
W01,
W02
FROM OPENQUERY(MACPAC,
'SELECT
P.Reference,
P.UAP,
P.W01,
P.W02
FROM AUTO.D805DATPOR.Production AS P
LEFT JOIN AUTO.D805DATPOR.Stock S
ON P.Reference = S.Reference AND
S.UAP =
CASE P.UAP
WHEN ''UAP1'' THEN ''M1''
WHEN ''UAP2'' THEN ''M2''
WHEN ''UAP3'' THEN ''M3''
WHEN ''UAP4'' THEN ''M4''
WHEN ''UAP5'' THEN ''M5''
WHEN ''UAP6'' THEN ''M6''
WHEN ''UAPP'' THEN ''PROTOS''
WHEN ''EXT'' THEN ''EXTR''
END
WHERE (P.Reference Not Like ''FS%'')
ORDER BY Reference DESC')
another method which gives error in UAP1 not a column in table L that might work using dual table for DB2
SELECT
Reference,
UAP,
W01,
W02
FROM OPENQUERY(MACPAC,
'SELECT
P.Reference,
P.UAP,
P.W01,
P.W02
FROM AUTO.D805DATPOR.Production AS P
JOIN
(
SELECT ''UAP1'' AS UAP1, ''M1'' AS UAP2 FROM sysibm.sysdummy1
UNION ALL SELECT ''UAP2'',''M2'' FROM sysibm.sysdummy1
UNION ALL SELECT ''UAP3'',''M3'' FROM sysibm.sysdummy1
UNION ALL SELECT ''UAP4'',''M4'' FROM sysibm.sysdummy1
UNION ALL SELECT ''UAP5'',''M5'' FROM sysibm.sysdummy1
UNION ALL SELECT ''UAP6'',''M6'' FROM sysibm.sysdummy1
UNION ALL SELECT ''UAPP'',''PROTOS'' FROM sysibm.sysdummy1
UNION ALL SELECT ''EXT'',''EXTR'' FROM sysibm.sysdummy1
) L
ON P.UAP = L.UAP1
INNER JOIN AUTO.D805DATPOR.Stock S
ON P.Reference = S.Reference AND S.UAP = L.UAP2
WHERE (P.Reference Not Like ''FS%'')
ORDER BY Reference DESC')
Try to use a link-subquery:
FROM AUTO.D805DATPOR.Production AS P
JOIN
(
SELECT ''UAP1'' AS UAP1,''M1'' AS UAP2 FROM DUAL
UNION ALL SELECT ''UAP2'',''M2'' FROM DUAL
UNION ALL SELECT ''UAP3'',''M3'' FROM DUAL
UNION ALL SELECT ''UAP4'',''M4'' FROM DUAL
UNION ALL SELECT ''UAP5'',''M5'' FROM DUAL
UNION ALL SELECT ''UAP6'',''M6'' FROM DUAL
UNION ALL SELECT ''UAPP'',''PROTOS'' FROM DUAL
UNION ALL SELECT ''EXT'',''EXTR'' FROM DUAL
) L
ON P.UAP=L.UAP1 -- !!!
INNER JOIN AUTO.D805DATPOR.Stock S
ON P.Reference = S.Reference AND S.UAP=L.UAP2 -- !!!
Or you can create a link-table in the Oracle and then use it in your query.
I think it'll be better because you can use it in other queries and insert there a new combinations.
Pseudo code:
CREATE TABLE UAP_LINK(
UAP1 VARCHAR2(20) NOT NULL,
UAP2 VARCHAR2(20) NOT NULL,
PRIMARY KEY(UAP1),
UNIQUE(UAP2)
)
INSERT UAP_LINK VALUES
UAP1, M1
UAP2, M2
UAP3, M3
UAP4, M4
UAP5, M5
UAP6, M6
UAPP, PROTOS
EXT , EXTR
One more variant with CASE:
FROM AUTO.D805DATPOR.Production AS P
INNER JOIN AUTO.D805DATPOR.Stock S
ON P.Reference = S.Reference
AND S.UAP=
CASE P.UAP
WHEN ''UAP1'' THEN ''M1''
WHEN ''UAP2'' THEN ''M2''
WHEN ''UAP3'' THEN ''M3''
WHEN ''UAP4'' THEN ''M4''
WHEN ''UAP5'' THEN ''M5''
WHEN ''UAP6'' THEN ''M6''
WHEN ''UAPP'' THEN ''PROTOS''
WHEN ''EXT'' THEN ''EXTR''
END

SQL Server - Struggling to group/sum values across multiple related tables

I'm running this query:
SELECT
g.PartNum,
g.Supplier,
(g.InitialQuantityToInventory + SUM(COALESCE(t.AmountInventoryAdjusted + t.AmountReturned, 0))) AS StockLevel
FROM
GoodsIn g
LEFT JOIN
Transfers t ON g.GoodsInNumber = t.GoodsInNumber
WHERE
g.PartNum = '123'
GROUP BY
g.PartNum, g.Supplier, g.InitialQuantityToInventory
And it's returns these results:
123,SUP1,67
123,NULL,18
123,NULL,0
123,NULL,45
123,NULL,0
However I would like the StockLevel (in the 3rd column) to SUM on the supplier name, even when it's null, so that my expected result should be:
123,SUP1,67
123,NULL,63
What am I doing wrong? The query should (across all GoodsIn Numbers that have the same PartNumber & Supplier) Sum the InitialQuantities and their Amounts Adjusted & Returned for each transfer associated with the GoodsIn record.
This is the data for that part & supplier in the GoodsIn Table:
GINum Part Num Supplier InitialQuantityToInventory
73367 123 NULL 81
73570 123 NULL 18
74154 123 NULL 320
74835 123 Sup1 0
74836 123 NULL 500
75738 123 Sup1 0
And this is the corresponding rows from the Transfers table (T being short for TransferNum):
GINum T Adj Ret
73367 1 -81 0
74154 1 -200 0
74154 2 -120 45
74835 1 67 0
74836 1 -500 0
75738 1 -300 0
75738 2 300 0
Do you need to not group by InitialQuantityToInventory?
;WITH Logs (Supplier, Initial, StockChange)
AS
(
SELECT
g.Supplier,
g.InitialQuantityToInventory,
(SUM(COALESCE(t.AmountInventoryAdjusted + t.AmountReturned,0))) AS StockChange
FROM
GoodsIn g
LEFT JOIN
Transfers t ON g.GoodsInNumber = t.GoodsId
GROUP BY
g.Supplier, g.InitialQuantityToInventory
)
SELECT
Supplier,
SUM(Initial) + SUM(StockChange) AS StockLevel
FROM
Logs
GROUP BY
Supplier
What might be happening is you're getting a row per unique InitialQuantityToInventory, but from what I gather, you want these to be summed, right?
This could probably be optimised further (and probably doesn't need a CTE), but hopefully it at least returns the data you expect.
I don't think you need to GROUP BY InitialQuantityToInventory. Try following query and let me know if this works for what you need.
SELECT
g.PartNum,
g.Supplier,
MAX(g.InitialQuantityToInventory) + SUM(COALESCE(t.AmountInventoryAdjusted + t.AmountReturned,0)) AS StockLevel
FROM
GoodsIn g
LEFT JOIN
Transfers t ON g.GoodsInNumber = t.GoodsInNumber
WHERE
g.PartNum = '123'
GROUP BY
g.PartNum, g.Supplier
Try this, group the Transfers before joining and grouping
SELECT
g.PartNum,
g.Supplier,
SUM(g.InitialQuantityToInventory + COALESCE(t.adjRet, 0))
FROM Goodsin g
LEFT JOIN
(
SELECT GINum, SUM(AmountInventoryAdjusted + AmountReturned) AS adjRet
FROM Transfers
GROUP BY GINum
) T
ON t.GINum = g.GiNum
GROUP BY g.PartNum, g.Supplier

Pivot Query - Missing records

I have a pivot query which works well until now, but there has been a requirement where I need to specify a condition in the unpivot query which would omit the rows and column values which are not matching with the condition and displays me null. However, I need to show those value as a part of final results.
I have tried to do union to include the missing values, but won't get the desired output. I am pasting my pivot query below along with the results which are displayed and which needs to be displayed as a result. Please help.
CURRENT QUERY
SELECT
OrderID, AccessName, Address1, Postcode
, Gen_Instr_1 AS "General Instructions for Install"
,Supplier_Name_1 AS "Supplier Name"
,Install_Job_Name_1 AS "Install Jobs"
,Install_Job_Status_1 AS "Install Job Status"
,Install_Job_Name_2 AS "EPR Jobs"
,Install_Job_Status_2 AS "EPR Job Status"
FROM
(
SELECT
OrderID, AccessName, Address1, Postcode
, col+'_'+CAST(rn AS VARCHAR(10)) col,
val
FROM
(
SELECT o.OrderID,
CAST(js.JobStatusID AS VARCHAR(50)) JobStatusId
, CAST(p.Name AS VARCHAR(50)) Install_Job_Name
, o.AccessName, o.Address1, o.Postcode
, CAST(oj.GeneralInstructions AS VARCHAR(50)) Gen_Instr
, CAST(s.CompanyName AS VARCHAR(50)) Supplier_Name
, oj.SupplierID
, CAST(js.Name AS VARCHAR(50)) Install_Job_Status
, ROW_NUMBER() OVER(PARTITION BY o.OrderID ORDER BY o.OrderID) rn
FROM
NEPCCO.Orders o
INNER JOIN NEPCCO.Clients c ON o.ClientID = c.ClientID
INNER JOIN NEPCCO.OrderJobs oj ON o.OrderID = oj.OrderID
INNER JOIN NEPCCO.Suppliers s ON oj.SupplierID = s.SupplierID
INNER JOIN NEPCCO.Products p ON oj.ProductID = p.ProductID
INNER JOIN NEPCCO.OrderStatus os ON o.OrderStatusID = os.OrderStatusID
INNER JOIN NEPCCO.JobStatus js ON oj.JobStatusID = js.JobStatusID
WHERE
o.OrderID IN (6981,6860,6982,6983) AND
(p.ProductID IN (35,36,37,38,38,40,41,42,43) OR p.ProductID IN (33,34))
AND s.CompanyName = 'Northern Gas Heating Ltd'
) d
UNPIVOT
(
val
FOR col IN (JobStatusId, Gen_Instr, Supplier_Name,Install_Job_Name, Install_Job_Status)
) un
) s
PIVOT
(
MAX(val)
FOR col IN (JobStatusID_1, Gen_Instr_1, Supplier_Name_1, Install_Job_Name_1, Install_Job_Status_1,
JobStatusID_2, Gen_Instr_2,
Install_Job_Name_2, Install_Job_Status_2
)
) piv
CURRENT RESULTS - SEE THE NULL VALUES IN LAST TWO COLUMNS
OrderID AccessName Address1 Postcode SupplierName Install Jobs Install Job Status EPR Jobs EPR Job Status
6981 Mrs Cespedes 73 Mill Lane WV11 1DQ Northern Gas Heating Ltd GC1 - 28 Complete NULL NULL
6983 Ms A Mirza 122 Pendleford Avenue WV6 9EN Northern Gas Heating Ltd GC1 - 28 Complete NULL NULL
Now, if I runn the inner unpivot query as below, I get following records/rows
Inner unpivot query
SELECT o.OrderID,
CAST(js.JobStatusID AS VARCHAR(50)) JobStatusId
, CAST(p.Name AS VARCHAR(50)) Install_Job_Name
, o.AccessName, o.Address1, o.Postcode
, CAST(oj.GeneralInstructions AS VARCHAR(50)) Gen_Instr
, CAST(s.CompanyName AS VARCHAR(50)) Supplier_Name
, oj.SupplierID
, CAST(js.Name AS VARCHAR(50)) Install_Job_Status
, ROW_NUMBER() OVER(PARTITION BY o.OrderID ORDER BY o.OrderID) rn1
FROM
NEPCCO.Orders o
INNER JOIN NEPCCO.Clients c ON o.ClientID = c.ClientID
INNER JOIN NEPCCO.OrderJobs oj ON o.OrderID = oj.OrderID
INNER JOIN NEPCCO.Suppliers s ON oj.SupplierID = s.SupplierID
INNER JOIN NEPCCO.Products p ON oj.ProductID = p.ProductID
INNER JOIN NEPCCO.OrderStatus os ON o.OrderStatusID = os.OrderStatusID
INNER JOIN NEPCCO.JobStatus js ON oj.JobStatusID = js.JobStatusID
WHERE
o.OrderID IN (6981,6860,6982,6983) AND
(p.ProductID IN (35,36,37,38,38,40,41,42,43) OR p.ProductID IN (33,34))
that produces following results
OrderID AccessName Address1 Postcode SupplierName Install Jobs Install Job Status EPR Jobs EPR Job Status
6860 6 AW EPR 01625555555 1 Gorsey Road SK9 5DU OGP 14 Cancelled 1
6981 4 AW EPR Mrs Cespedes 73 Mill Lane WV11 1DQ Ian Barnhurst 1 Complete 1
6981 4 GC1 - 28 Mrs Cespedes 73 Mill Lane WV11 1DQ Northern Gas Heating Ltd 403 Complete 2
6982 4 AW EPR Installer Mr N Singh 115 Oxbarn Avenue WV3 7HQ Northern Gas 414 Complete 1
6983 4 AW EPR Installer Ms A Mirza 122 Pendleford Avenue WV6 9EN Northern Gas 414 Complete 1
6983 4 GC1 - 28 Ms A Mirza 122 Pendleford Avenue WV6 9EN Northern Gas Heating Ltd 403 Complete 2
Problem
Now, if you see carefully the above result set, which has the order id's 6860, 6982, which is not included as a part of above result because it hasn't got the supplier name as Northern Gas Heating Ltd, moreover, the results which are displayed on first query, omits the values from order id's 6981, 6983, also, because they have different suppliers.
Also, if you notice, with the records being displayed in first query, the values with row number 2 are not included.
I tried my best but failed. #bluefeet, your expertise highly required over here. Any clarifications please ask.

To find percentage compliance using T-SQL

I'm not an expert in T-SQL so here I'm trying to find the % compliance for flu vaccine ,TB test and resiprator test by supervisor for medical staffs. Each employee has a supervisor name linked to their employee info. The below code works fine and it's giving me the % for the above tests. The problem is that I want to get the ID, Name and Department by Supervisor and the % compliance.
The expected output is like this:
Supervisor ID NAME Dept %Flu %TB %FIT
Elaine Jong 98% 100% 52%
001 MARY SURGERY
002 SUSAN SURGERY
James Ande 100% 98% 78%
267 JIM INPATIENT
789 SAM INPATIENT
Current OUTPUT
%Flu %TB %FIT
Elaine Jong 98% 100% 52%
James Ande 100% 98% 78%
And the Query:
SELECT E.FLDSUPRNAME AS Supervisor,
1.0*SUM(
CASE WHEN I.FLDDATE IS NULL
THEN 0 ELSE 1
END)/SUM(1) AS Percent_Flu_Compliant,
1.0*SUM(
CASE WHEN F.FLDDATE IS NULL OR (F.FLDDATE+365) < GETDATE()
THEN 0 ELSE 1
END) / SUM(1)
AS Percent_Fit_Compliant,
1.0*SUM(
CASE WHEN PPDx.FLDDATEDUE IS NULL
AND TBSSx.FLDDATEDUE IS NULL
AND CDUEx.FLDDATEDUE IS NULL
THEN 1 ELSE 0
END) /SUM(1) AS Percent_TB_Compliant
FROM EMPLOYEE E
LEFT OUTER JOIN DEPT D
ON D.FLDCODE= E.FLDDEPT
LEFT OUTER JOIN IMMUNE I ON I.FLDEMPLOYEE = E.FLDREC_NUM AND I.FLDTYPE IN ('109', '111')
AND I.FLDDATE = ( SELECT MAX(FLDDATE) FROM IMMUNE I2 WHERE E.FLDREC_NUM = I2.FLDEMPLOYEE
AND I2.FLDTYPE IN ('109','111') ) AND I.FLDDATE >= #Flu_Date AND I.FLDDATE <= GETDATE()
LEFT OUTER JOIN FITTEST F ON E.FLDREC_NUM = F.FLDEMPLOYEE
AND F.FLDDATE = (SELECT MAX(FLDDATE) FROM FITTEST F2 WHERE E.FLDREC_NUM = F2.FLDEMPLOYEE)
LEFT OUTER JOIN REQEXAM PPDx
ON PPDx.FLDEMPLOYEE = E.FLDREC_NUM
AND PPDx.FLDPHYSICAL = '110' AND
PPDx.FLDDATEDUE <= getdate()
LEFT OUTER JOIN REQEXAM PPDL
ON PPDL.FLDEMPLOYEE = E.FLDREC_NUM
AND PPDL.FLDPHYSICAL = '110'
LEFT OUTER JOIN REQEXAM TBSSx
ON TBSSx.FLDEMPLOYEE = E.FLDREC_NUM
AND TBSSx.FLDPHYSICAL = 'TBSS' AND
TBSSx.FLDDATEDUE <= getdate()
LEFT OUTER JOIN REQEXAM TBSSL
ON TBSSL.FLDEMPLOYEE = E.FLDREC_NUM
AND TBSSL.FLDPHYSICAL = 'TBSS'
LEFT OUTER JOIN REQEXAM CDUEx
ON CDUEx.FLDEMPLOYEE = E.FLDREC_NUM
AND CDUEx.FLDPHYSICAL = '109' AND
CDUEx.FLDDATEDUE <= getdate()
LEFT OUTER JOIN EMP S
ON S.FLDREC_NUM = E.FLDREC_NUM
WHERE E.FLDCOMP = #company
AND E.FLDSTATUS = 'A'
AND E.FLDSUPRNAME <> ' '
AND E.FLDID <> ' '
GROUP BY E.FLDSUPRNAME
ORDER BY E.FLDSUPRNAME
If I add ID,NAME and Dept on select and group by , SUM(1) will turn to 1 or 0, so I'm getting either 100% or 0% for all supervisors.
Any help on this is really appreciated.
thanks for your time.
USE an UNION, add blank columns to your first query and remove the order by:
SELECT (CASE WHEN ID IS NULL THEN Supervisor ELSE '' END) ,ID, name,dept,Percent_Flu_Compliant,Percent_TB_Compliant,Percent_Fit_Compliant FROM
(
SELECT E.FLDSUPRNAME AS Supervisor, NULL as ID, NULL as name, NULL as dept
(...)
GROUP BY hiddensupervisor, Supervisor, ID, name, dept
UNION ALL
SELECT E.FLDSUPRNAME Supervisor, E.id, E.name, E.dept, NULL as Percent_Flu_Compliant, NULL as Percent_TB_Compliant, NULL asPercent_Fit_Compliant
FROM Employee
) as q
ORDER BY supervisor, (CASE WHEN ID IS NULL THEN 1 ELSE 0 END),ID
we add the hidden supervisor column to be able to fit employees under their supervisor but leave that field blank there (we also could not add it and use case in the outer query, dunno which one would be faster). Apparently we have to try with case

Resources