Counting sum of items of type - sql

What i what to do is from this :
|type|quantity|
+----+--------+
|shoe| 10 |
|hat | 2 |
|shoe| 7 |
|shoe| 1 |
|hat | 5 |
to get this :
|shoes|hats|
+-----+----+
| 18 | 7 |
How can i do that? So far I hadn't come up with a working query, I think it should look something like that:
SELECT
SUM(CASE type WHEN 'shoe' then quantity ELSE 0 END) AS "shoes",
SUM(CASE type WHEN 'hat' then quantity ELSE 0 END) AS "hats"
FROM items
GROUP BY type

Just drop the group by. You want only one row:
SELECT
SUM(CASE type WHEN 'shoe' then quantity ELSE 0 END) AS "shoes",
SUM(CASE type WHEN 'hat' then quantity ELSE 0 END) AS "hats"
FROM items ;

Related

How to get the grand total and the subtotal in one row?

Here is the expected output.
ID | GRAND_TOTAL | CHANNEL_1 | CHANNEL_2
1 | 100.00 | 50.00 | 50.00
2 | 500.00 | 100.00 | 400.00
But my query resulted like this:
ID | GRAND_TOTAL | CHANNEL_1 | CHANNEL_2
1 | 100.00 | 50.00 | 0
2 | 100.00 | 0 | 50.00
1 | 500.00 | 100.00 | 0
2 | 500.00 | 0 | 400.00
This is what I tried in my query.
SELECT
ID,
SUM(Amount) AS GRAND_TOTAL,
CASE WHEN CHANNEL_ID = 1 THEN AMOUNT ELSE 0 END CHANNEL_1,
CASE WHEN CHANNEL_ID = 2 THEN AMOUNT ELSE 0 END CHANNEL_2
FROM
CHANNEL_AMOUNT
GROUP BY
ID, CHANNEL_ID, AMOUNT
GROUP BY ____ means "I want one result row per ____". You don't want one result row per ID, cannel and amount, but only one per ID. Hence: GROUP BY id. Then you want sums per channel, so use SUM.
SELECT
id,
SUM(amount) AS grand_total,
SUM(CASE WHEN channel_id = 1 THEN amount ELSE 0 END) AS channel_1,
SUM(CASE WHEN channel_id = 2 THEN amount ELSE 0 END) AS channel_2
FROM channel_amount
GROUP BY id
ORDER BY id;
(In standard SQL this would be SUM(amount) FILTER (WHERE channel_id = 1), but SQL Server doesn't feature the filter clause yet, so we use a case expression inside the aggregation function.)
Looks like you want grouping by Id only
SELECT
ID,
SUM(Amount) AS GRAND_TOTAL,
SUM(CASE WHEN CHANNEL_ID = 1 THEN AMOUNT ELSE 0 END) CHANNEL_1,
SUM(CASE WHEN CHANNEL_ID = 2 THEN AMOUNT ELSE 0 END) CHANNEL_2
FROM
CHANNEL_AMOUNT
GROUP BY
ID
You can just try GROUP BY ID.
SELECT
ID,
SUM(Amount) AS GRAND_TOTAL,
CASE WHEN CHANNEL_ID = 1 THEN AMOUNT ELSE 0 END CHANNEL_1,
CASE WHEN CHANNEL_ID = 2 THEN AMOUNT ELSE 0 END CHANNEL_2
FROM
CHANNEL_AMOUNT
GROUP BY
ID

how to group column as per its unique value and get count in to different column as per its value?

I am having a Category table as follows,
i want retrieve following results according to scStatusvalue and its count group by catID
catID | 0 | 2 | 3
----- |---|---|---
2 | 1 | 0 | 1
3 | 1 | 1 | 0
4 | 2 | 0 | 1
5 | 0 | 1 | 0
I tried this,select catID,count(scStatus) as [Count] from tableName group by catID,scStatus order by catID but i cant get into column that values.
`
Use a pivot query:
SELECT catID,
SUM(CASE WHEN scStatus = 0 THEN 1 ELSE 0 END) AS [0],
SUM(CASE WHEN scStatus = 2 THEN 1 ELSE 0 END) AS [2],
SUM(CASE WHEN scStatus = 3 THEN 1 ELSE 0 END) AS [3]
FROM Category
GROUP BY catID
pivot operator
select *
from (select catID,scStatusvalue from t) t
pivot (count(scStatusvalue) for scStatusvalue in ([0],[2],[3])) t

Count who paid group by 1, 2 or 3+

I have a payment table like the example below and I need a query that gives me how many IDs paid (AMOUNT > 0) 1 time, 2 times, 3 or more times. Example:
+----+--------+
| ID | AMOUNT |
+----+--------+
| 1 | 50 |
| 1 | 0 |
| 2 | 10 |
| 2 | 20 |
| 2 | 15 |
| 2 | 10 |
| 3 | 80 |
+----+--------+
I expect the result:
+-----------+------------+-------------+
| 1 payment | 2 payments | 3+ payments |
+-----------+------------+-------------+
| 2 | 0 | 1 |
+-----------+------------+-------------+
ID 1: Paid 1 time (50). The other payment is 0, so I did not count. So, 1 person paid 1 time.
ID 2: Paid 3 times (10,20,15). So, 1 person paid 3 or more time.
ID 3: Paid 1 time (80). So, 2 persons paid 1 time.
I'm doing manually on excel right now but I'm pretty sure there is a more practical solution. Any ideas?
A little sub-query will do the trick
Declare #YOurTable table (ID int, AMOUNT int)
Insert into #YourTable values
( 1 , 50 ),
( 1 , 0) ,
( 2 , 10) ,
( 2 , 20) ,
( 2 , 15) ,
( 2 , 10) ,
( 3 , 80)
Select [1_Payment] = sum(case when Cnt=1 then 1 else 0 end)
,[2_Payment] = sum(case when Cnt=2 then 1 else 0 end)
,[3_Payment] = sum(case when Cnt>2 then 1 else 0 end)
From (
Select id
,Cnt=count(*)
From #YourTable
Where Amount<>0
Group By ID
) A
Returns
1_Payment 2_Payment 3_Payment
2 0 1
To get the output you want try using a table to form the data and then SELECT from that:
with c as (
select count(*) count from mytable where amount > 0 group by id)
select
sum(case count when 1 then 1 else 0 end) "1 Payment"
, sum(case count when 2 then 1 else 0 end) "2 Payments"
, sum(case when count > 2 then 1 else 0 end) "3 Payments"
from c
Here is an example you can play with to see how the query is working.

Count days on a column case

I would like to create a SQL script that counts the number of age days and the something like:(The catch is I got the days value of breaking value of one column by case to three columns) This is the output I have created.
Days0To30 Days30to60 Daysto60to90
----------------------------------
50$ | 10$ | 90$
60$ | 0 | 10$
0 | 0 | 5$
0 | 10$ | 0
10$ | 0 | 0
0$ | 0 | 0
1240 | 0 | 0
I would like to create a SQL script that counts the number of age days and the something like:
------------------------------------------
Days0To30 | 4
Days30to60 | 2
Daysto60to90 | 3
You can use conditional aggregation:
select count(case when Days0To30 <> 0 then 1 end) as Days0To30,
count(case when Days30to60 <> 0 then 1 end) as Days30to60,
count(case when Daysto60to90 <> 0 then 1 end) as Daysto60to90
from yourtable
SELECT SUM(CASE WHEN Days0To30 > 0 THEN 1 ELSE 0 END) as Days0To30 ,
SUM(CASE WHEN Days30to60 > 0 THEN 1 ELSE 0 END) as Days30to60,
SUM(CASE WHEN Daysto60to90 > 0 THEN 1 ELSE 0 END) as Daysto60to90
FROM SOME_TABLE

Get Month columns from datetime column and count entries

I have the following table:
| ID | Name | DateA | TimeToWork | TimeWorked |
|:--:|:----:|:----------:|:----------:|:----------:|
| 1 |Frank | 2013-01-01 | 8 | 5 |
| 2 |Frank | 2013-01-02 | 8 | NULL |
| 3 |Frank | 2013-01-03 | 8 | 7 |
| 4 |Jules | 2013-01-01 | 4 | 9 |
| 5 |Jules | 2013-01-02 | 4 | NULL |
| 6 |Jules | 2013-01-03 | 4 | 3 |
The table is very long, every person has an entry for every day in a year. For each person I have the Date he worked (DateA), the hours he has to work according to contract (TimeToWork) and the hours he worked (TimeWorked). As you can see some days a person didnt work on a day he had to. This is when a person took a full day overtime.
What I try to accomplish is to get the following table out of the first one above.
| Name | January | Feburary | March | ... | Sum |
|:----:|:----------:|:--------:|:-----:|:---:|:---:|
|Frank | 2 | 0 | 1 | ... | 12 |
|Jules | 5 | 1 | 3 | ... | 10 |
For each month I want to count all days where a person took A FULL day off and sum all up in the Sum column.
I tried something like Select (case when Datetime(month, DateA = 1 then count(case when timetowork - (case when timeworked then 0 end) = timetowork then 1 else 0 end) end) as 'January' but my TSQL is just not that good and the code doent work at all. Btw using this my select command would be about 40 lines.
I really would appreciate if anyone could help me or give me a link to a good source so I can read myself into it.
If I understand the question right, than Gordon Linoff's answer is a good beginning, but doesn't deal with "full day off".
select Name,
sum(case when month(DateA) = 01 and TimeWorked is null then 1 else 0 end) as Jan,
sum(case when month(DateA) = 02 and TimeWorked is null then 1 else 0 end) as Feb,
...
sum(case when month(DeteA) = 12 and TimeWorked is null then 1 else 0 end) as Dec,
sum(case when TimeWorked is null then 1 else 0 end) as Sum
from table T
where year(DateA) = 2013
group by name
This method solves the problem?
The correct syntax is conditional aggregation:
select name,
sum(case when month(datea) = 1 then timeworked else 0 end) as Jan,
sum(case when month(datea) = 2 then timeworked else 0 end) as Feb,
. . .
sum(case when month(datea) = 12 then timeworked else 0 end) as Dec,
sum(timeworked)
from table t
where year(datea) = 2013
group by name;
The CASE can be removed using bit logic
SELECT name
, January = SUM((1 - CAST(MONTH(DateA) - 1 as bit))
* (1 - CAST(COALESCE(TimeWorked, 0) as bit)))
, February = SUM((1 - CAST(MONTH(DateA) - 2 as bit))
* (1 - CAST(COALESCE(TimeWorked, 0) as bit)))
...
, December = SUM((1 - CAST(MONTH(DateA) - 12 as bit))
* (1 - CAST(COALESCE(TimeWorked, 0) as bit)))
, Total = SUM((1 - CAST(COALESCE(TimeWorked, 0) as bit)))
FROM table1
GROUP BY name;
To check if there is a dayoff the formula is:
(1 - CAST(COALESCE(TimeWorked, 0) as bit))
that is equivalent to TimeWorked IS NULL: the CAST to BIT return 1 for every value different from 0, 1 - BIT invert those values.
The month filter is:
(1 - CAST(MONTH(DateA) - %month% as bit))
using the same idea as before this formula return 1 only for the given month (the cast give 1 for every other month, the 1 - BIT invert that result)
Multipling the two formulas we have the days off only for the given month
You can get your required result by using pivot also. You can get more information about pivot here http://technet.microsoft.com/en-in/library/ms177410(v=sql.105).aspx
Also you can get your output using the following query. I did it for up to April only. You can extend it up to December.
Select [Name], [January], [February], [March], [April]
From
(
Select Name, MName, DaysOff from
(
select Name, DATENAME(MM, dateA) MName,
count(case isnull(timeworked,0) when 0 then 1 else null end) DaysOff
from tblPivot
Where Year(DateA) = 2013
group by Name, DATENAME(MM, dateA)
) A ) As B
pivot(Count(DaysOff)
For MName in ([January], [February],[March],[April])
) As Pivottable;