How to group database column? - sql

I need to get a sales Ref. wise report which have several filters. I tried this query to generate the report.
SELECT
sp.SlpCode,
sp.SlpName,
sp.Telephone,
COUNT(od.DocNum) count,
ISNULL((SELECT COUNT(od.U_ArtWork) WHERE od.U_ArtWork = 'NotRec'), 0) Artwork,
ISNULL((SELECT COUNT(od.U_DetailPending) WHERE od.U_DetailPending = 'No'), 0) DetailPrinting
FROM
OSLP sp
LEFT JOIN
ORDR od ON SP.SlpCode = od.SlpCode
WHERE
sp.Telephone IS NOT NULL
GROUP BY
sp.SlpCode, sp.SlpName, sp.Telephone,
od.U_ArtWork, od.U_DetailPending
ORDER BY
sp.SlpName ASC;
The results are like this:
But I need those results like this:

You may try aggregating only on the three columns SlpCode, SlpName, and Telephone:
SELECT
sp.SlpCode,
sp.SlpName,
sp.Telephone,
COUNT(od.DocNum) count,
COUNT(CASE WHEN od.U_ArtWork = 'NotRec' THEN 1 END) AS Artwork,
COUNT(CASE WHEN od.U_DetailPending = 'No' THEN 1 END) AS DetailPrinting
FROM OSLP sp
LEFT JOIN ORDR od
ON SP.SlpCode = od.SlpCode
WHERE
sp.Telephone IS NOT NULL
GROUP BY
sp.SlpCode,
sp.SlpName,
sp.Telephone,
ORDER BY
sp.SlpName;

Remove od.U_ArtWork,od.U_DetailPending from group by - you are using these columns in aggregation so no need to add in group by clause
SELECT
sp.SlpCode,
sp.SlpName,
sp.Telephone,
COUNT(od.DocNum) count,
COUNT(case when od.U_ArtWork = 'NotRec' then od.U_ArtWork end) Artwork,
COUNT(case when od.U_DetailPending='No' then od.U_DetailPending end) DetailPrinting
FROM OSLP sp
LEFT JOIN ORDR od
ON SP.SlpCode = od.SlpCode
WHERE
sp.Telephone IS NOT NULL
GROUP BY
sp.SlpCode,
sp.SlpName,
sp.Telephone
ORDER BY
sp.SlpName ASC

Related

Avoid NULL value in CASE SQL SERVER

How to avoid NULL values in CASE and SUM by P.Id. Problem is that i have more than one DPB.ProductTypeId in DPB table
SELECT P.[Id],
CASE
WHEN DPB.ProductTypeId = 1 THEN SUM(DPB.BonusAmount)
END AS [CasinoBonus]
FROM Player P
JOIN PlayerBonus DPB ON P.[Id] = DPB.[PlayerId]
group by P.[Id],DPB.ProductTypeId
use case when inside sum
SELECT P.[Id],
sum(CASE
WHEN DPB.ProductTypeId = 1 THEN DPB.BonusAmount
else 0
END) AS [CasinoBonus]
FROM Player P
JOIN PlayerBonus DPB ON P.[Id] = DPB.[PlayerId]
where P.[Id] is not null and DPB.[PlayerId] is not null
group by P.[Id],DPB.ProductTypeId
The case should be the argument to the sum(). You query should look like this:
SELECT P.[Id],
SUM(CASE WHEN DPB.ProductTypeId = 1 THEN DPB.BonusAmount
END) AS [CasinoBonus]
FROM Player P JOIN
PlayerBonus DPB
ON P.[Id] = DPB.[PlayerId]
GROUP BY P.[Id];
Note that you don't want DPB.ProductTypeId in the GROUP BY.
That said, you may simply want:
SELECT P.[Id],
SUM(DPB.BonusAmount) AS [CasinoBonus]
FROM Player P LEFT JOIN
PlayerBonus DPB
ON P.[Id] = DPB.[PlayerId] AND
DPB.ProductTypeId = 1
GROUP BY P.[Id];
Moving the condition to the WHERE clause removes the need for the CASE entirely. The LEFT JOIN keeps all players, even those that don't have that product type.

Aggregate case when inside non aggregate query

I have a pretty massive query that in its simplest form looks like this:
select r.rep_id, u.user_id, u.signup_date, pi.application_date, pi.management_date, aum
from table1 r
left join table2 u on r.user_id=u.user_id
left join table3 pi on u.user_id=pi.user_id
I need to add one more condition that gives me count of users with non null application date per rep (like: rep 1 has 3 users with filled application dates), and assign it into categories (since 3 users, rep is a certain status category). This looks something like this:
case when sum(case when application_date is not null then 1 else 0 end) >=10 then 'status1'
when sum(case when application_date is not null then 1 else 0 end) >=5 then 'status2'
when sum(case when application_date is not null then 1 else 0 end) >=1 then 'status3'
else 'no_status' end as category
However, if I was to simply add it to the select statement, all reps will becomes of status1 because the sum() is done over all advisors with application dates filled:
select r.rep_id, u.user_id, u.signup_date, pi.application_date, pi.management_date, aum,
(
select case when sum(case when application_date is not null then 1 else 0 end) >=10 then 'status1'
when sum(case when application_date is not null then 1 else 0 end) >=5 then 'status2'
when sum(case when application_date is not null then 1 else 0 end) >=1 then 'status3'
else 'no_status' end as category
from table3
) as category
from table1 r
left join table2 u on r.user_id=u.user_id
left join table3 pi on u.user_id=pi.user_id
Can you assist with having the addition to my query to be across reps and not overall? Much appreciated!
Based on your description, I think you need a window function:
select r.rep_id, u.user_id, u.signup_date, pi.application_date, pi.management_date, aum,
count(pi.application_date) over (partition by r.rep_id) as newcol
from table1 r left join
table2 u
on r.user_id = u.user_id left join
table3 pi
on u.user_id = pi.user_id;
You can use the count() in a case to get ranges, if that is what you prefer.

How to convert two rows value in a single row?

I have below sql server query data
Looking for solution.
SQL Query:
SELECT
p.ProjectName,
i.ItemName,
inv.TransactionDirection,
SUM(inv.TransactionQty) AS TransactionQuantity
FROM INVTransaction inv
JOIN BDProject p ON p.ProjectID=inv.ProjectID
JOIN MDItem i ON i.ItemID=inv.ItemID
GROUP BY p.ProjectName,
i.ItemName,
inv.TransactionDirection
I think you just want conditional aggregation:
SELECT p.ProjectName, i.ItemName,
SUM(CASE WHEN inv.TransactionDirection = 'IN' THEN inv.TransactionQty ELSE 0 END) as IN_Quantity,
SUM(CASE WHEN inv.TransactionDirection = 'OUT' THEN inv.TransactionQty ELSE 0 END) as OUT_Quantity,
SUM(CASE WHEN inv.TransactionDirection = 'IN' THEN inv.TransactionQty
WHEN inv.TransactionDirection = 'OUT' THEN -inv.TransactionQty
ELSE 0
END) as Balance
FROM INVTransaction inv JOIN
BDProject p
ON p.ProjectID = inv.ProjectID JOIN
MDItem i ON i.ItemID = inv.ItemID
GROUP BY p.ProjectName, i.ItemName
You can use Pivot for this. Below is working query.
SELECT PROJECTNAME,ITEMNAME,[IN],[OUT] ,ISNULL([IN],0)-ISNULL([OUT],0) AS BALANCE FROM
(SELECT PROJECTNAME,ITEMNAME,TRANSACTIONDIRECTION,TRANSACTIONQUANTITY FROM TRANSACTIONS
)A
PIVOT (SUM(TRANSACTIONQUANTITY) FOR TRANSACTIONDIRECTION IN ([IN],[OUT])) AS PVT
Replace TRANSACTIONS with your table name
As #Gordon Linoff almost provided solution but for balance column you can replace
SUM(inv.TransactionQty) as Balance
With
SUM(CASE WHEN inv.TransactionDirection = 'IN'
THEN inv.TransactionQty
ELSE -1*inv.TransactionQty END) as Balance

SQL Server 2008 case statement to count records and not another record with same date but different result

I need to count the number of id's where the Name and Eventname can have either 'Accept' or 'reject' for a value on the same date. How can i write a case statement to only use the 'Accept' value? i have tried many ways and still counts them all. Still counts the 'reject' records.
Any help is greatly appreciated.
example below:
select th.NAME,
COUNT(distinct th.HICN_CD) AS HICN_COUNT,
case th.EVENTNAME
when 'accept' then 'Accept'
when 'reject' then 'Reject' ELSE 'N/A'
END AS Event_Name
from #temp_hicn th
left join #temp_maxdate tm
on tm.HICN_CD = th.HICN_CD
group by th.NAME,
th.EVENTNAME
order by th.NAME ;
It sounds like you want conditional aggregation:
select th.NAME, COUNT(distinct th.HICN_CD) AS HICN_COUNT ,
sum(case th.EVENTNAME when 'accept' then 1 ELSE 0 END) AS NumAccept
from #temp_hicn th left join
#temp_maxdate tm
on tm.HICN_CD = th.HICN_CD
group by th.NAME
order by th.NAME;
If you want to count distinct value of HICN_CD for accepts:
select th.NAME,
COUNT(distinct case th.EVENTNAME when 'accept' then th.HICN_CD end) AS HICN_COUNT ,
sum(case th.EVENTNAME when 'accept' then 1 ELSE 0 END) AS NumAccept
from #temp_hicn th left join
#temp_maxdate tm
on tm.HICN_CD = th.HICN_CD
group by th.NAME
order by th.NAME;
SELECT DISTINCT TH.HICN_CD, TH.NAME, TH.EVENTNAME, TM.MAX_DATE
INTO #TEMP_ACCEPT
FROM #TEMP_HICN TH
LEFT JOIN #TEMP_MAXDATE TM
ON TM.HICN_CD = TH.HICN_CD
AND TM.MAX_DATE = TH.MAX_DATEID
GROUP BY TH.MEDICARE_HICN_CD, TH.NAME, TH.EVENTNAME, TM.MAX_DATE;
SELECT DISTINCT TH.MEDICARE_HICN_CD, TH.NAME, TH.EVENTNAME, TM.MAX_DATE
INTO #TEMP_REJECT
FROM #TEMP_HICN TH
LEFT JOIN #TEMP_MAXDATE TM
ON TM.HICN_CD = TH.HICN_CD
AND TM.MAX_DATE = TH.MAX_DATEID
WHERE TH.EVENTNAME = 'REJECT'
AND TH.HICN_CD + TH.NAME NOT IN (SELECT HICN_CD + NAME FROM #TEMP_ACCEPT)
GROUP BY TH.HICN_CD, TH.NAME, TH.EVENTNAME, TM.MAX_DATE;
SELECT *
INTO #TEMP_EVENT
FROM #TEMP_ACCEPT
UNION
SELECT *
FROM #TEMP_REJECT;
WITH EVENT_DUP AS (
SELECT DISTINCT HICN_CD, NAME, COUNT() AS 'EVENTS'
FROM #TEMP_EVENT
GROUP BY HICN_CD, NAME
HAVING COUNT() > 1
)
DELETE FROM #TEMP_EVENT
WHERE HICN_CD + NAME IN (SELECT HICN_CD + NAME FROM EVENT_DUP)
AND MAX_DATE IS NULL;
SELECT EV.NAME, EV.EVENTNAME ,COUNT(DISTINCT EV.HICN_CD) AS HICN_COUNT
FROM #TEMP_EVENT EV
LEFT JOIN #TEMP_MAXDATE TM
ON TM.HICN_CD = EV.HICN_CD
GROUP BY EV.NAME, EV.EVENTNAME
ORDER BY EV.NAME;

Add where clause to count and not entire query without using subquery

The below query works but the "o.opendate is not null and o.orderdate is not null and o.closedate is null and o.canceldate is null" portion of the where clause needs to only apply to the orderID count (orderCount). Right now it is applying to the entire result set and that is not what I want. How can I change the query to do this? Also these tables are very large so I am relying heavily on indexes and trying not to use subquerys for performance reasons. Any help would be appreciated
select s.ZipCode, count(o.[OrderID]) orderCount, b.Longitude, b.Latitude, b.ordering
from ZipCodeServiceAvailability s
left join pdx_orders_view o on s.ZipCode = left(o.[ZipCode], 5)
left join ZipCodeBoundaries b on s.ZipCode = b.ZipCode
Where s.state = 'TX' and Ordering % 10 = 0 and
o.opendate is not null and o.orderdate is not null and o.closedate is null and o.canceldate is null
Group By s.ZipCode, IsServiced, b.Longitude, b.Latitude, b.Ordering
Order by s.ZipCode, b.Ordering
You need a case statement with a SUM:
select sum(case when o.opendate is not null and o.orderdate is not null and o.closedate is null and o.canceldate is null
then 1 else 0
end) as OrderCount
You should then remove the conditions from the where clause.
You can do what you want with a having clause.
select s.ZipCode, count(o.[OrderID]) orderCount, b.Longitude, b.Latitude, b.ordering
from ZipCodeServiceAvailability s
left join pdx_orders_view o on s.ZipCode = left(o.[ZipCode], 5)
left join ZipCodeBoundaries b on s.ZipCode = b.ZipCode
Where s.state = 'TX' and Ordering % 10 = 0 and
o.opendate is not null
Group By s.ZipCode, IsServiced, b.Longitude, b.Latitude, b.Ordering
Having count(o.[OrderID]) is not null
Order by s.ZipCode, b.Ordering