Calculate extra column in group by - sql-server

In sure this should be simple, but I'm having a brain fart over it.
In SQL Server 2005, how do you add an "extra count" to a GROUP BY query?
Consider the following...
;WITH DATA AS (
SELECT 1 AS ID, 1 AS TYPEID, 0 AS ACTIONNEEDED
UNION
SELECT 2 AS ID, 1 AS TYPEID, 0 AS ACTIONNEEDED
UNION
SELECT 3 AS ID, 2 AS TYPEID, 0 AS ACTIONNEEDED
UNION
SELECT 4 AS ID, 2 AS TYPEID, 1 AS ACTIONNEEDED
UNION
SELECT 5 AS ID, 2 AS TYPEID, 0 AS ACTIONNEEDED
)
SELECT TYPEID, COUNT(*) AS TOTAL
FROM DATA
GROUP BY TYPEID
The result is...
TYPEID TOTAL
1 2
2 3
But what I need is an extra column that totals the number of rows where ACTIONNEEDED=1...
TYPEID TOTAL ACTIONNEEDED
1 2 0
2 3 1
Note: unfortunately due to project constraints, I'm restricted to SQL Server 2005 compatible answers

You can use SUM with an inner CASE statement:
SELECT
TYPEID,
COUNT(*) AS TOTAL,
SUM(CASE WHEN ActionNeeded = 1 THEN 1 ELSE 0 END) AS ACTIONNEEDED
FROM DATA
GROUP BY TYPEID

Related

Date Comparison of Two Tables in SQL SERVER

I had this Data,
Table One :
EmpID Date Absent
1 01/01/2018 1
1 01/02/2018 1
1 02/05/2018 1
1 03/25/2018 1
1 04/01/2018 0
1 05/02/2018 1
1 06/03/2018 1
Table Two
ID Amount DateEffective
1 5.00 02/06/2018
2 3.00 05/02/2018
3 10.00 06/03/2018
Desired Output
EmpID Month Year Absent Penalty
1 January 2018 2 5.00
1 February 2018 1 5.00
1 March 2018 1 3.00
1 April 2018 0 3.00
1 May 2018 1 13.00
1 June 2018 1 10.00
This is my Code
SELECT { fn MONTHNAME(one.Date) } AS MonthName, YEAR(one.Date) AS Year, SUM(one.Absent) AS Absent,
(
SELECT top 1 two.DailyRate
FROM table_two as two
WHERE EmpID = '1'
AND one.Date <= two.EffectivityDate
)
FROM table_one as one
WHERE EmpID = '1'
GROUP BY { fn MONTHNAME(one.Date) }, MONTH(one.Date), YEAR(one.DTRDate)
ORDER BY Year(one.Date),month(one.Date)
and it shows an error :
Column 'one.Date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
please help for this issue...
Thanks
Try this :
SELECT
one.EmpID
,DATENAME(MONTH,one.Date) AS [MonthName]
,YEAR(one.Date) AS [Year]
,SUM(one.Absent) AS [Absent]
,(SELECT top 1 two.Amount
FROM table_two as two
WHERE two.ID = one.EmpID
AND YEAR(two.DateEffective) >= YEAR(one.Date)
AND MONTH(two.DateEffective) >=MONTH(one.Date)
) AS [Penalty]
FROM table_one as one
WHERE
one.EmpID = '1'
GROUP BY one.EmpID,DATENAME(MONTH,one.Date), MONTH(one.Date), YEAR(one.Date)
ORDER BY Year(one.Date),month(one.Date)
From my understanding to do this,
select e.EmpID
,datename(month,e.Date)[month]
,year(e.Date) [year]
,sum(e.Absent) as [Abscount]
,a.Amount
from
empl e left join abs a
on datename(month,e.Date)=DATENAME(month,a.DateEffective)
group by e.EmpID,DATENAME(MONTH,e.Date), MONTH(e.Date), YEAR(e.Date) , a.Amount
order by Abscount desc
Revert me if any clarifications needed...
is this helpful.?
Create Table #TabOne(EmpID int,[Date] Date,[Absent] Bit)
Create Table #TabTwo(ID int,Amount float,DateEffective Date)
Insert into #TabOne
SELECT 1,'01/01/2018',1 Union All
SELECT 1,'01/02/2018',1 Union All
SELECT 1,'02/05/2018',1 Union All
SELECT 1,'03/25/2018',1 Union All
SELECT 1,'04/01/2018',0 Union All
SELECT 1,'05/02/2018',1 Union All
SELECT 1,'06/03/2018',1
Insert into #TabTwo
Select 1,5.00 ,'02/06/2018' Union All
Select 2,3.00 ,'05/02/2018' Union All
Select 3,10.00,'06/03/2018'
;with cte1
As
(
Select One.EmpID,MONTH(one.[Date]) As [mon],YEAR(one.[Date]) As [Year],two.Amount,one.[Absent],
ROW_NUMBER() OVER(partition by One.EmpID,One.[Date] order by DATEDIFF(dd,two.DateEffective,one.[Date]) desc) as rn
from #TabOne one
LEFT JOIN #TabTwo two on one.[Date]<=two.DateEffective
)
Select EmpID,DATENAME(month, DATEADD(month, [mon]-1, CAST('2008-01-01' AS datetime))) As [Month],
[Year],SUM(CASE WHEN [Absent]=0 then 0 ELSE 1 END) As [Absent] ,MAX(Amount) As Penalty
from cte1
where rn=1
Group by EmpID,[Year],[mon]
order by EmpID,[Year],[mon]
Drop Table #TabOne
Drop Table #TabTwo

SQL Server: How to get the top 'N' max occurrences from each group

I have a below dataset and I am trying to get max occurrences of CID per each OID.
IF OBJECT_ID('TEMPDB..#SS',N'U') IS NOT NULL
DROP TABLE #SS
GO
SELECT * INTO #SS FROM (
SELECT 1 AS OID,501 AS CID
UNION ALL
SELECT 1 AS OID,503 AS CID
UNION ALL
SELECT 1 AS OID,502 AS CID
UNION ALL
SELECT 1 AS OID,501 AS CID
UNION ALL
SELECT 1 AS OID,501 AS CID
UNION ALL
SELECT 2 AS OID,502 AS CID
UNION ALL
SELECT 2 AS OID,502 AS CID
UNION ALL
SELECT 2 AS OID,502 AS CID
UNION ALL
SELECT 2 AS OID,501 AS CID
UNION ALL
SELECT 1 AS OID,503 AS CID
)A
GO
In above sample dataset, I need to get 2 CID per each OID which occurred maximum times. The expected result could be:
OID CID
1 501
1 503
2 501
2 502
This cannot be a duplicate to SQL Select top frequent records because I need this sub-queries and SQL-Server would not accept ORDER BY in sub-query and eventually I need a ranking function to solve my issue. Ranking function was not used in the link provided.
You can do this pretty easily utilizing ROW_NUMBER. Thanks for Tab Alleman for the clarification on your requirements.
select *
from
(
select *
, RowNum = ROW_NUMBER() over (partition by OID order by count(*) desc)
from #SS
group by OID
, CID
) x
where x.RowNum <= 2
order by x.OID
, x.CID

Union rows to columns in SQL server

This is the table "tbltask",
task Ship_Operator Pick_Operator Pack_Operator
1 john kevin steve
2 kevin kevin john
3 steve john john
4 steve steve steve
5 john steve john
Now I need to get the total amount for everyone: ship, pick, pack
name ship Total pick Total pack Total
john 2 1 3
kevin 1 2 0
steve 2 2 2
I can use three statement to get the result:
select [Ship_Operator] ,count(*) as task_total from tbltask
where [Ship_Operator] in ('john','kevin','steve')
group by [Ship_Operator]
select [Pick_Operator] ,count(*) as task_total from tbltask
where [Pick_Operator] in ('john','kevin','steve')
group by [Pick_Operator]
select [Pack_Operator] ,count(*) as task_total from tbltask
where [Pack_Operator] in ('john','kevin','steve')
group by [Pack_Operator]
Is it possible to use one SQL statement?
Your help will be appreciated!
unpivot and pivot back:
with t(task,Ship_Operator,Pick_Operator,Pack_Operator) as (
select '1','john','kevin','steve' union all
select '2','kevin','kevin','john' union all
select '3','steve','john','john' union all
select '4','steve','steve','steve' union all
select '5','john','steve','john')
-------Test data set up ends here------------
select
name, Ship_Operator ship_total, Pick_Operator pick_total, Pack_Operator pack_total
from t unpivot (
name for operation in (Ship_Operator, Pick_operator, Pack_Operator)
) as x pivot (
count(task) for operation in ([Ship_Operator],[Pick_Operator],[Pack_Operator])
) as x;
Produces:
Another way is to use UNPIVOT only and then conditionally aggregate:
with t(task,Ship_Operator,Pick_Operator,Pack_Operator) as (
select '1','john','kevin','steve' union all
select '2','kevin','kevin','john' union all
select '3','steve','john','john' union all
select '4','steve','steve','steve' union all
select '5','john','steve','john')
-------Test data set up ends here------------
select
name,
count(case when operation = 'Ship_Operator' then 1 end) ship,
count(case when operation = 'Pick_Operator' then 1 end) pick,
count(case when operation = 'Pack_Operator' then 1 end) pack
from t unpivot (
name for operation in (Ship_Operator, Pick_operator, Pack_Operator)
) as x
group by name;
Produces:
Use UNION to combine all name and add a new column to just identify the different values.
Query
SELECT t.[Name],
SUM(CASE t.[Col1] WHEN 'Ship' THEN 1 ELSE 0 END) AS [Ship Total],
SUM(CASE t.[Col1] WHEN 'Pick' THEN 1 ELSE 0 END) AS [Pick Total],
SUM(CASE t.[Col1] WHEN 'Pack' THEN 1 ELSE 0 END) AS [Pack Total]
FROM(
SELECT 'Ship' AS [col1], [Ship_operator] as [Name]
FROM [tbltask]
UNION ALL
SELECT 'Pick', [Pick_operator]
FROM [tbltask]
UNION ALL
SELECT 'Pack' AS [col1], [Pack_operator]
FROM [tbltask]
)t
GROUP BY t.[Name];
And if you want the result particularly for those three names. Then add a WHERE condition in the sub-queries.

SQL count number of groups

I have a table with pallets, items, item quantity:
pallet | item | qty
-------------------
1 1 2
1 2 4
2 3 2
2 5 3
3 4 4
I need to find count(pallet), count(item), sum(qty)
count(pallets) | count(items) | sum(qty)
----------------------------------------
3 5 15
I can get the sum(qty) and count(item) with
select count(0) as totalItems, sum(qty) as total from table
Is there a way to get the number of pallets without a sub-query?
Yes, use DISTINCT
select count(distinct pallet) as pallets,
sum(qty) as total,
count(*) as totalItems
from your_table
Simply use Distinct to avoid duplicate records to be count.
count(Distinct pallet)
Your query like this
select
count(distinct pallet) as pallets,
sum(qty) as Total,
count(item) AS [Total Items]
it will give output AS :

Is it possible to write single query for following scenario?

Is it possible to write single query for following scenario?
Scenario -
Table -
column name - id date isPaid
values - 1 1/1/2011 1
2 1/2/2011 1
3 1/3/2011 0
4 1/4/2011 0
5 1/5/2011 0
I want a result set which contains (all ispaid = 1) and (only 1 row of ispaid = 0 whose date is smaller).
Result set:
column name - id date isPaid
values - 1 1/1/2011 1
2 1/2/2011 1
3 1/3/2011 0
Thanks
You can use UNIONdocs
SELECT
[id],
[date],
[isPaid]
FROM
[tablename]
WHERE
[ispaid] = 1
UNION ALL
SELECT TOP 1
[id],
[date],
[isPaid]
FROM
[tablename]
WHERE
[ispaid] = 0
ORDER BY
[date] ASC
This should do what you need in SQL Server 2005 and higher.
select
[id],
[date],
isPaid
from (
select
[id],
[date],
isPaid,
ROW_NUMBER() over (partition by ispaid order by date) as row
from table_name t ) a
where ispaid = 1
or row = 1
order by [date]
Assuming date will be provided to the query by user, for which data is to be retrieved
select t.*
from table t,
(select Top 1 id, date, ispaid
from table
where ispaid = 0 and date<?) np
where (t.ispaid=1 and t.date = ? ) OR (t.id = np.id)

Resources