SQL Server CASE - WHEN - ELSE - sql-server

I have 2 tables like this:
Table CT: Number, CtID, Date, CTIE
Table VT: Number, VtID, Quantities
And my code:
SELECT
MAX(CT.Date), MAX(CT.CtID), VT.VtID,
SUM(VT.Quantities) AS SumVT,
CASE
WHEN CT.CTIE = 0 THEN SUM(VT.Quantities)
ELSE 0
END AS IMPORT,
CASE
WHEN CT.CTIE = 1 THEN SUM(VT.Quantities)
ELSE 0
END AS EXPORT
FROM
CT
INNER JOIN
VT ON CT.Number = VT.Number
GROUP BY
VT.VtID, CT.CTIE
ORDER BY
VT.VtID
This code works fine but the result is not what I want. With some VtID that have both CTIE = 1 and CTIE = 1, SQL now returns 2 separate rows with same VtID, one for CTIE = 0 and one for CTIE = 1. But I need it to display only 1 row for each VtID instead of 2.

Remove CT.CTIE in the group by and place your case statements inside the aggregate function
SElECT
MAX(CT.Date), MAX(CT.CtID), VT.VtID, SUM(VT.Quantities) AS SumVT,
SUM(CASE WHEN CT.CTIE = 0 THEN VT.Quantities ELSE 0 END) AS IMPORT,
SUM(CASE WHEN CT.CTIE = 1 THEN VT.Quantities ELSE 0 END) AS EXPORT
FROM CT INNER JOIN VT ON CT.Number=VT.Number
GROUP BY VT.VtID
ORDER by VT.VtID

Related

how to count quantity of different between 2 tables?

i need to count different between 2 tables (same table from 2 different days) to see what have changed.
for example table 1:
table 2:
and i want to get this table:
i try this code:
select a.of_key , case when a.color != b.color then count (a.color) ELSE 0 END AS color,
case when a.side != b.side then count (a.side) else 0 end as side
from 130720 A right JOIN 100720 B
ON a.of_key = b.of_key and a.num = b.bum
group by a.of_key
it is not working
please help
thanks!
Put your aggregate outside the case statement:
select a.of_key , SUM(case when a.color != b.color then 1 ELSE 0 END) AS color,
SUM(case when a.side != b.side then 1 else 0 end) as side
from 130720 A right JOIN 100720 B
ON a.of_key = b.of_key and a.num = b.bum
group by a.of_key

SQL Server : select when record is 1 then return line else return the 0 record

I need a little help with a query.
I have written a script that brings back an order number and the number of containers needed (code below):
SELECT
CONI.CONTNO,
CONI.ITEMNO,
CONI.[WEIGHT],
CONI.QTY,
STOK.PGROUP,
CASE WHEN CPRO.TNTCOL = 1 THEN 1
WHEN CPRO.TNTCOL = 0 THEN 0
WHEN CPRO.TNTCOL IS NULL THEN 0 END AS [TNT],
CONI.RECID,
CPRO.RECKEY
INTO
#SUB
FROM
ContItems CONI
LEFT JOIN
ContractItemProfiles CPRO ON CONI.RECID = CPRO.RECKEY
JOIN
Stock STOK ON CONI.ITEMNO = STOK.ITEMNO
WHERE
STOK.PGROUP LIKE 'FLI%'
SELECT
#SUB.CONTNO,
#SUB.TNT,
SUM(#SUB.QTY) AS [Number of flight cases]
FROM
#SUB
WHERE
#SUB.CONTNO = '123/321581'
GROUP BY
#SUB.CONTNO,
#SUB.TNT
DROP TABLE #SUB
I get this result:
Contno TNT Number of flight cases
------------------------------------------
123/321581 0 20.00
123/321581 1 1.00
I need to conditionally bring back the line that has the TNT = 1 Else if there isn't a 1 in the TNT column then bring back the record with 0
I hope this is explained enough.
That case can be replaced with
isnull(CPRO.TNTCOL, 0)
select top 1
from ( SELECT #SUB.CONTNO,
#SUB.TNT,
SUM(#SUB.QTY) AS [Number of flight cases]
FROM #SUB
WHERE #SUB.CONTNO = '123/321581'
) t
order by TNT desc

select distinct with parent-child and return boolean for at least one child with a value?

I am currently searching for orders that have at least one orderline (product) with a certain boolean set:
- the product is a subscription product
- the product is a setup product
If one of the orderlines has this value set to 1, I want to return this in the query per DISTINCT order ID.
This does not seem to work for me:
SELECT DISTINCT [ORDER].[order_id]
,[ORDERLINE].[is_subscription] AS hasSubArticles
,[ORDERLINE].[is_setup] AS hasSetupArticles
FROM [ORDER]
LEFT JOIN [ORDERLINE]
ON [ORDER].[order_id] = [ORDERLINE].[f_order_id]
WHERE [G_ORDER].[status] = 1
ORDER BY [ORDER].[order_id]
,[ORDERLINE].[is_subscription] AS hasSubArticles
,[ORDERLINE].[is_setup] AS hasSetupArticles
When I check the returned records, I receive duplicate ORDER records:
order_id hasSubArticles hasSetupArticles
----------------------------------------
17804 NULL NULL
17804 1 0
I want to return only 1 record per order ID, thus this isn't working for me.
What am I doing wrong?
Distinct does not work for your requirement. MAX, Min functions are not allowed to use with bit type. You could use Group by and SUM like this
SELECT
[ORDER].[order_id]
,CASE WHEN SUM( CASE WHEN [ORDERLINE].[is_subscription] = 1 THEN 1 ELSE 0 END) > 0 THEN 1
ELSE 0
END AS hasSubArticles
,CASE WHEN SUM( CASE WHEN [ORDERLINE].[is_setup] = 1 THEN 1 ELSE 0 END) > 0
THEN 1
ELSE 0
END hasSetupArticles
FROM [ORDER]
LEFT JOIN [ORDERLINE]
ON [ORDER].[order_id] = [ORDERLINE].[f_order_id]
WHERE [G_ORDER].[status] = 1
GROUP BY [ORDER].[order_id]

Calculate a Running Monthly Average in SQL Server

We want to create a data-set which shows the monthly average count in our equipment table broken down by it's status: Active, Scrapped, New.
The more I ponder this it seems that the only way to accomplish this is to first create a container temp table and evaluate each record using a cursor.
Can this be accomplished without a temp table?
The following just shows the fields we're working with:
SELECT a1.statusdate, a1.CreateDate,
RunningTotalActive = count([status]='Active'),
RunningTotalScrapped = count([status]='Scrapped'),
NewEquipment = count(Month(a1.CreateDate) )
FROM dbo.Equipment AS a1
INNER JOIN dbo.Equipment AS a2
ON a2.statusdate <= a1.CreateDate
GROUP BY a1.statusdate
ORDER BY a1.statusdate desc
I'm making a few SWAGs about your data, but the idea is to average the sums over simple counts by month; using CTEs.
; WITH A AS (
SELECT a1.statusdate,
Active = CASE a1.[status] WHEN 'Active' THEN 1 ELSE 0 END,
Scrapped = CASE a1.[status] WHEN 'Scrapped' THEN 1 ELSE 0 END,
New = CASE WHEN a2.statusdate = a1.CreateDate THEN 1 ELSE 0 END --Guessing here that "new" means status date and create date are the same
FROM dbo.Equipment AS a1
INNER JOIN dbo.Equipment AS a2
ON a2.statusdate <= a1.CreateDate --"status" can be older than "create" for a piece of equipment? Not sure I understand this criteria. May need sample data.
), B AS (
SELECT Y = DATEPART(YEAR, statusdate)
, M = DATEPART(MONTH, statusdate)
, SumActive = SUM(Active)
, SumScrapped = SUM(Scrapped)
, SumNew = SUM(New)
FROM A
GROUP BY DATEPART(YEAR, statusdate), DATEPART(MONTH, statusdate)
)
SELECT Y, M,
RunningTotalActive = AVG(SumActive)OVER(PARTITION BY Y,M ORDER BY Y,M),
RunningTotalScrapped = AVG(SumScrapped)OVER(PARTITION BY Y,M ORDER BY Y,M),
NewEquipment = AVG(SumNew)OVER(PARTITION BY Y,M ORDER BY Y,M)
FROM B;
Can you show some sample data?
I had modified your script following my understanding. Can you try it?
SELECT YEAR(a1.statusdate) AS yr,MONTH(a1.statusdate) AS mon,
RunningTotalActive = count(CASE WHEN a1.[status]='Active' THEN 1 ELSE NULL END ), -- or SUM(CASE WHEN [status]='Active' THEN 1 ELSE 0 END ),
RunningTotalScrapped = count(CASE WHEN a1.[status]='Scrapped' THEN 1 ELSE NULL END),
NewEquipment = count(CASE WHEN YEAR(a1.CreateDate)*12+ MONTH(a1.CreateDate)= YEAR(a1.statusdate)*12+ MONTH(a1.statusdate)) THEN 1 ELSE NULL END )
FROM dbo.Equipment AS a1
GROUP BY YEAR(a1.statusdate),MONTH(a1.statusdate)
ORDER BY YEAR(a1.statusdate),MONTH(a1.statusdate) DESC

SQL not doing the join correctly

I have a SQL statement with some JOIN condition it is working fine for all of them but not the last one the code is below:
SELECT
A.EMPL_CTG,
B.DESCR AS PrName,
SUM(A.CURRENT_COMPRATE) AS SALARY_COST_BUDGET,
SUM(A.BUDGET_AMT) AS BUDGET_AMT,
SUM(A.BUDGET_AMT)*100/SUM(A.CURRENT_COMPRATE) AS MERIT_GOAL,
SUM(C.FACTOR_XSALARY) AS X_Programp,
SUM(A.FACTOR_XSALARY) AS X_Program,
COUNT(A.EMPLID) AS EMPL_CNT,
COUNT(D.EMPLID),
SUM(CASE WHEN A.PROMOTION_SECTION = 'Y' THEN 1 ELSE 0 END) AS PRMCNT,
SUM(CASE WHEN A.EXCEPT_IND = 'Y' THEN 1 ELSE 0 END) AS EXPCNT,
(SUM(CASE WHEN A.PROMOTION_SECTION = 'Y' THEN 1 ELSE 0 END)+SUM(CASE WHEN A.EXCEPT_IND = 'Y' THEN 1 ELSE 0 END))*100/(COUNT(A.EMPLID)) AS PEpercent
FROM
EMP_DTL A INNER JOIN EMPL_CTG_L1 B ON A.EMPL_CTG = B.EMPL_CTG
INNER JOIN
ECM_PRYR_VW C ON A.EMPLID=C.EMPLID
INNER JOIN ECM_INELIG D on D.EMPL_CTG=A.EMPL_CTG and D.YEAR=YEAR(getdate())
WHERE
A.YEAR=YEAR(getdate())
AND B.EFF_STATUS='A'
GROUP BY
A.EMPL_CTG,
B.DESCR
ORDER BY B.DESCR
The COUNT(D.EMPLID) is returning the same value as COUNT(A.EMPLID) but I need the count of EMPLIDs for Table D in the join condition, any help?
COUNT() (and also the other GROUP BY aggregate functions) doesn't process only the rows from one of the tables.
They work on all the rows produced by the JOIN. If the JOIN without GROUP BY produces 42 rows then COUNT(*) and COUNT(1) returns 42 while COUNT(A.EMPLID) and COUNT(D.EMPLID) return the number of not-NULL values in those columns.
In order to get the number of rows extracted from one of the tables the you should use COUNT(DISTINCT). It ignores the NULL values and also the duplicates produced by the JOIN.
Change COUNT(D.EMPLID) to COUNT(DISTINCT D.EMPLID).

Resources