SQL sum total each column in last row - sql

I wish SQL for SUM each column(IPO and UOR) in TOTAL in second last. And GRAND TOTAL(Sum IPO + UOR) in the last one. Thank you so much
No Code IPO UOR
----------------------
1 D173 1 0
2 D176 3 0
3 D184 1 1
4 D185B 1 0
5 D187 1 2
6 F042 3 0
7 ML004 12 3
8 TTPMC 2 0
9 Z00204 1 0
------------------
TOTAL (NOS) 25 6
-------------------------
GRAND TOTAL (NOS) 31
Here is my code, :
SELECT
SUM(CASE WHEN IPOType = 'IPO' THEN 1 ELSE 0 END) as IPO,
SUM(CASE WHEN IPOType = 'UOR' THEN 1 ELSE 0 END) as UOR
FROM IPO2018
GROUP BY OriProjNo
it can show like this
No Code IPO UOR
----------------------
1 D173 1 0
2 D176 3 0
3 D184 1 1
4 D185B 1 0
5 D187 1 2
6 F042 3 0
7 ML004 12 3
8 TTPMC 2 0
9 Z00204 1 0
------------------

Generally speaking, you want to leave totals and sub-totals to whatever tool you are presenting your data in, as they will be able to handle the formatting with significantly more ease. In addition, your desired output does not have the same number of columns (Grand Total row only has one numeric) so even if you did shoehorn this in to the same dataset, the column headings wouldn't make sense.
That said, you can return group totals via the with rollup statement. This will provide an additional row with the aggregate totals for the group. Where there is more than one group in your data, you will get a sub-total row for each group and a total row for the entire dataset:
declare #t table(c nvarchar(10),t nvarchar(3));
insert into #t values ('D173','IPO'),('D176','IPO'),('D176','IPO'),('D176','IPO'),('D184','IPO'),('D184','UOR'),('D185B','IPO'),('D187','IPO'),('D187','UOR'),('D187','UOR'),('F042','IPO'),('F042','IPO'),('F042','IPO'),('TTPMC','IPO'),('TTPMC','IPO'),('Z00204','IPO'),('ML004','UOR'),('ML004','UOR'),('ML004','UOR'),('ML004','IPO'),('ML004','IPO'),('ML004','IPO'),('ML004','IPO'),('ML004','IPO'),('ML004','IPO'),('ML004','IPO'),('ML004','IPO'),('ML004','IPO'),('ML004','IPO'),('ML004','IPO'),('ML004','IPO');
select row_number() over (order by grouping(c),c) as n
,case when grouping(c) = 1 then 'TOTAL (NOS)' else c end as c
,sum(case when t = 'IPO' then 1 else 0 end) as IPO
,sum(case when t = 'UOR' then 1 else 0 end) as UOR
from #t
group by c
with rollup
order by grouping(c)
,c;
Output:
+----+-------------+-----+-----+
| n | c | IPO | UOR |
+----+-------------+-----+-----+
| 1 | D173 | 1 | 0 |
| 2 | D176 | 3 | 0 |
| 3 | D184 | 1 | 1 |
| 4 | D185B | 1 | 0 |
| 5 | D187 | 1 | 2 |
| 6 | F042 | 3 | 0 |
| 7 | ML004 | 12 | 3 |
| 8 | TTPMC | 2 | 0 |
| 9 | Z00204 | 1 | 0 |
| 10 | TOTAL (NOS) | 25 | 6 |
+----+-------------+-----+-----+

Related

How to combine data from 2 tables -- which join, what conditions?

Consider the following 2 tables.
TableDE
ID country key1 key2
------------------------
1 US 1 null
1 US 1 null
1 US 1 null
2 US null null
3 US 1 1
4 DE 1 1
5 DE null null
5 DE null null
TableUS
ID key1 key2
--------------
1 null null
2 null 1
4 1 1
8 null 1
2 null 1
2 null 1
9 1 null
I need a distinct overview of all IDs, combining data from both tables:
ID inTableDe country DEkey1 DEkey2 inTableUS USkey1 USKey2
-----------------------------------------------------------------
1 1 US 1 0 1 0 0
2 1 US 0 0 1 0 1
3 1 US 1 1 0 0 0
4 1 DE 1 1 1 1 1
5 1 DE 0 0 0 0 0
8 0 0 0 1 1 0 1
9 0 0 0 1 1 1 0
I hope it speaks for itself:
ID 8 and ID 9 have 0 in the first column bc they aren't in tableDE
ID 8 and ID 9 have 0 in the country column bc this field doesn't exist in tableUS
ID 3 has 0 in inTableUS bc it only exists in tableDE
the key values are copied from the original tables
an ID is not unique: it can appear many times in both tables. However: the values for key1 and key2 will always be the same for each ID within the same table.
I have been messing for hours now with this; I have this now:
select de.[ID],
de.[country],
case when (de.[ID] in (select distinct [ID] from [tableDE]) then 1 else 0 end as [inTableDE],
case when (de.[ID] in (select distinct [ID] from [tableUS]) then 1 else 0 end as [inTableUS],
de.[key1] as [DEKey1],
de.[key2] as [DEKey2],
us.[key1] as [USKey1],
us.[key2] as [USKey2],
from dbo.[tableDE] de
full outer join dbo.[tableUS] us on de.[ID] = us.[ID]
where de.[country] = 'US'
and (de.[key1] = 1 or de.[key2] = 1 or us.[key1] = 1 or us.[key2] = 1)
group by de.[ID], us.[ID]
But this keeps giving me only values that are in both tables.
What am I doing wrong?
You sem to want aggregation on top of the full join:
select
coalesce(de.id, us.id) as id,
case when de.id is null then 0 else 1 end as intablede,
max(de.country) as country,
coalesce(max(de.key1), 0) as dekey1,
coalesce(max(de.key2), 0) as dekey2,
case when us.id is null then 0 else 1 end as intableus,
coalesce(max(us.key1), 0) as uskey1,
coalesce(max(us.key2), 0) as uskey2
from dbo.tablede de
full join dbo.tableus us on de.id = us.id
group by de.id, us.id
order by id
Demo on DB Fiddle:
id | intablede | country | dekey1 | dekey2 | intableus | uskey1 | uskey2
-: | --------: | :------ | -----: | -----: | --------: | -----: | -----:
1 | 1 | US | 1 | 0 | 1 | 0 | 0
2 | 1 | US | 0 | 0 | 1 | 0 | 1
3 | 1 | US | 1 | 1 | 0 | 0 | 0
4 | 1 | DE | 1 | 1 | 1 | 1 | 1
5 | 1 | DE | 0 | 0 | 0 | 0 | 0
8 | 0 | null | 0 | 0 | 1 | 0 | 1
9 | 0 | null | 0 | 0 | 1 | 1 | 0

How to create column for every single integer within a range in SQLite?

Here's some sample data from my table:
day_number daily_users_count
1 1
3 1
6 1
7 1
9 2
10 2
I need all day_number values, from 1 to max(day_number), and I want daily_users_count to be zero if it isn't mentioned in this table.
It should look something like this:
day_number daily_users_count
1 1
2 0
3 1
4 0
5 0
6 1
7 1
8 0
9 2
10 2
I think a left join with a table which has a number column with all integers from 1 to max(day_number) would work, if I put a default value for daily_users_count as 0.
What I don't get is how to create such a table where all integers within a certain range are present. Any alternate solutions or any ways to do this would be much appreciated.
You can do it with a recursive CTE which will return all the day_numbers including the missing ones and then a LEFT join to the table:
with cte as (
select min(day_number) day_number from tablename
union all
select day_number + 1 from cte
where day_number < (select max(day_number) from tablename)
)
select c.day_number,
coalesce(t.daily_users_count, 0) daily_users_count
from cte c left join tablename t
on t.day_number = c.day_number
See the demo.
Results:
| day_number | daily_users_count |
| ---------- | ----------------- |
| 1 | 1 |
| 2 | 0 |
| 3 | 1 |
| 4 | 0 |
| 5 | 0 |
| 6 | 1 |
| 7 | 1 |
| 8 | 0 |
| 9 | 2 |
| 10 | 2 |

Compare one value with other values within a group SQL Server

I have below table where column names are Item, Point and IsCorrect.
Item | Point | IsCorrect | Not actual column, just logic
-----+-------+-----------+--------------------
1 | 5 | 0 | 5 >= 6
1 | 8 | 0 | 8 >= 6
1 | 9 | 0 | 9 >= 6
1 | 6 | 1 | 6 >= 6
2 | 8 | 0 | 8 >= 7
2 | 7 | 1 | 7 >= 7
2 | 8 | 0 | 8 >= 7
2 | 9 | 0 | 9 >= 7
3 | 2 | 0 | 2 >= 9
3 | 5 | 0 | 5 >= 9
3 | 8 | 0 | 8 >= 9
3 | 9 | 1 | 9 >= 9
I want to first group by Item, get a Point value where IsCorrect = 1, compare it with other point values (as shown in 4th column). If all condition matched within a group, then select that item. I am expecting following result.
Item | Point | IsCorrect
-----+-------+----------
2 | 8 | 0
2 | 7 | 1
2 | 8 | 0
2 | 9 | 0
I want to use partition, not group by. Thank you so much for your help.
Window functions come to mind:
select t.*
from (select t.*,
max(case when iscorrect = 1 then point end) over (partition by item) as point_correct,
min(point) over (partition by item) as min_point
from t
) t
where min_point >= point_correct;
You could also do this with a subquery. Something like this:
select t.*
from t
where t.item in (select t2.item
from t t2
group by t2.item
having min(t2.point) >= min(case when t2.iscorrect then point end)
);
That is, for each item, compare the minimum point value to the "correct" point value.

SQL column sum and difference

my table, I want to create three columns in single-column, reprinted now.
id | date | type | total
------ | ------ | ------ | -----
1 | 01.10.2016| Paypal | 50
2 | 03.10.2016| credit | 40
3 | 05.10.2016| Cash | 50
4 | 06.10.2016| payment| 100
5 | 07.10.2016| Cash | 20
6 | 15.10.2016| Skrill | 10
7 | 18.10.2016| payment| 20
8 | 19.10.2016| Paypal | 10
9 | 19.10.2016| payment| 20
10 | 22.10.2016| Cash | 40
11 | 23.10.2016| Skrill | 10
my table, I want to create three columns in single-column, reprinted now.
SELECT id,date,type,total
(select (
sum(case when type="Paypal" then total else 0 end)+
sum(case when type="credit" then total else 0 end))+
sum(case when type="Cash" then total else 0 end) ) as receiv,
(Select(
sum(case when type="payment" then total else 0 end)) AS payment,
(Select sum(receiv -payment) FROM totals t2
WHERE (t2.date <= t1.date) and (t2.id <= t1.id) order by t1.date) AS remainder
FROM totals t1
group by date, type
order by id,date
--
The following query for the sql code?
Type = "Paypal, credit, Cash" sums "receiv" sums and Type = "payment" sums will be added to the "remainder" column.
id | date | type | receiv| payment| remainder
------ | ------ | ------ | ------| ------ | ------
1 | 01.10.2016| Paypal | 50 | 0 | 50
2 | 03.10.2016| credit | 40 | 0 | 90
3 | 05.10.2016| Cash | 50 | 0 | 140
4 | 06.10.2016| payment| 0 | 100 | 40
5 | 07.10.2016| Cash | 20 | 0 | 60
6 | 15.10.2016| Skrill | 10 | 0 | 70
7 | 18.10.2016| payment| 0 | 20 | 50
8 | 19.10.2016| Paypal | 10 | 0 | 60
9 | 19.10.2016| payment| 0 | 20 | 40
10 | 22.10.2016| Cash | 40 | 0 | 80
11 | 23.10.2016| Skrill | 10 | 0 | 90
Running total is easier in other databases which have analytical functions. In MySQL, you can do this with a correlated sub-query.
select id,dt,type,
case when type <> 'payment' then total else 0 end receiv,
case when type = 'payment' then total else 0 end payment,
case when type <> 'payment' then total else 0 end
- case when type = 'payment' then total else 0 end
+ coalesce((select sum(case when type <> 'payment' then total else 0 end)
- sum(case when type = 'payment' then total else 0 end)
from yourtable where id < y.id),0)
from yourtable y
Sample Demo

issue with joins ins my query, how to populate null values as zero

My query is to fetch data for last 5 weeks.
select z.week,
sum(case when i.severity=1 then 1 else 0 end) as 1
sum(case when i.severity=2 then 1 else 0 end) as 2
sum(case when i.severity=3 then 1 else 0 end) as 3
sum(case when i.severity=4 then 1 else 0 end) as 4
from instance as i
and left outer join year as z on convert(varchar(10),z.date,101)=convert(varchar(10),i.created,101)
and left outer join year as z on convert(varchar(10),z.date,101)=convert(varchar(10),i.closed,101)
where i.group in '%Teams%'
and z.year=2013
and z.week<=6 and z.week>1
here there are few weeks in my instance table, where there will be not even an single row. so here im not getting null or zero... instead the entire row is not at all prompting.
my present output.
week | 1 | 2 | 3 | 4
---------------------
2 | 0 | 1 | 8 | 5
3 | 2 | 3 | 4 | 9
5 | 1 | 0 | 0 | 0
but i need output like the below...
week | 1 | 2 | 3 | 4
---------------------
2 | 0 | 1 | 8 | 5
3 | 2 | 3 | 4 | 9
4 | 0 | 0 | 0 | 0
5 | 1 | 0 | 0 | 0
6 | 0 | 0 | 0 | 0
How to get the desired outputi n sql
try this
select z.week,
sum(case when i.severity=1 then 1 else 0 end) as 1
sum(case when i.severity=2 then 1 else 0 end) as 2
sum(case when i.severity=3 then 1 else 0 end) as 3
sum(case when i.severity=4 then 1 else 0 end) as 4
from year as z
left outer join instance as i on
convert(varchar(10),z.date,101)=convert(varchar(10),i.created,101)
and convert(varchar(10),z.date,101)=convert(varchar(10),i.closed,101)
where (i.group is null or i.group in '%Teams%')
and z.year=2013
and z.week<=6 and z.week>1
I'm not sure how the query works where you alias year twice to z. But, assuming that's not a problem, you can change the LEFT OUTER JOIN to RIGHT OUTER JOIN. Or, if you don't like the RIGHT OUTER JOIN, rework the SELECT so that the FROM clause references the year table.