How to make total row on footer like this with serverside DataTable
| Name | Boy | Girl |
| Boy1 | - | |
| Girl1 | | - |
| Boy2 | - | |
| Total | 2 | 1 |
I use this query but the result only show 1 data (it should be 3 data for example)
select name, sum(case when sex = "male" then 1 else 0 end) as boy, sum(case when sex = "female" then 1 else 0 end) as girl' from student;
Thank you
If your database supports ROLLUP functionality, then you can try the following:
SELECT
name,
SUM(CASE WHEN sex = "male" THEN 1 ELSE 0 END) AS boy,
SUM(CASE WHEN sex = "female" THEN 1 ELSE 0 END) AS girl
FROM student
GROUP BY name
WITH ROLLUP
If you database does not support ROLLUP, then can use a UNION to add a record on the bottom for the total:
SELECT
name,
SUM(CASE WHEN sex = "male" THEN 1 ELSE 0 END) AS boy,
SUM(CASE WHEN sex = "female" THEN 1 ELSE 0 END) AS girl
FROM student
GROUP BY name
UNION ALL
SELECT
'total',
SUM(CASE WHEN sex = "male" THEN 1 ELSE 0 END),
SUM(CASE WHEN sex = "female" THEN 1 ELSE 0 END)
FROM student
ORDER BY
CASE WHEN name = 'total' THEN 1 ELSE 0 END,
name
Related
I have following three tables
table 1
mf_tab
id
seq
mfr
1234
1
goog
1234
2
apple
table 2
flg_tab
id
seq
flag
1234
1
REL
1234
2
REJ
table 3
pn_tab
id
seq
pn
1234
1
pxyz
1234
2
pabc
I would like the data in following format
id
Mfr1
mfr2
flag1
flag2
pn1
pn2
1234
goog
apple
REL
REJ
pxyz
pabc
Also I would have another case where all there columns are in one table as below. How to obtain smilar result from below table.
id
seq
Mfr
flag
pn
1234
1
goog
REL
pxyz
1234
2
apple
REJ
pabc
thanks
I can pivot one by one table but could not find a way to pivot multiple tables.
Thanks
An often used way to pivot is conditional aggregation:
select
id,
max(case when seq = 1 then t1.mfr end) as mfr1,
max(case when seq = 2 then t1.mfr end) as mfr2,
max(case when seq = 1 then t2.flag end) as flag1,
max(case when seq = 2 then t2.flag end) as flag2,
max(case when seq = 1 then t3.pn end) as pn1,
max(case when seq = 2 then t3.pn end) as pn2
from t1
join t2 using (id, seq)
join t3 using (id, seq)
group by id
order by id;
I have requirement in which msn column need to break into rangefrom and rangeto
table
num msn date
1ab 5 25/2/2019
1ab 7 25/2/2019
1ab 8 25/2/2019
1ac 8 25/4/2019
1ad 9 25/5/2019
1ad 10 25/5/2019
1ad 11 25/5/2019
output should like this if msn is not continuous then same value goes to rangefrom and rangeto if continuous then min value will go to rangefrom and max value will go rangeto based on date and num
num rangefrom rangeto date
1ab 5 5 25/2/2019
1ab 7 8 25/2/2019
1ad 9 11 25/4/2019
With LAG() and LEAD() window functions and a CTE:
with cte as (
select t.*,
case when "msn" - lag("msn") over (partition by "num", "date" order by "msn") = 1 then 0 else 1 end isfrom,
case when lead("msn") over (partition by "num", "date" order by "msn") - "msn" = 1 then 0 else 1 end isto
from tablename t
)
select c1."num", c1."msn" rangefrom, min(c2."msn") rangeto, c1."date"
from cte c1 inner join cte c2
on c2."num" = c1."num" and c2."date" = c1."date"
and (
(c1.isfrom = 1 and c2.isto = 1 and c1."msn" < c2."msn")
or
(c1.isfrom = 1 and c1.isto = 1 and c1."msn" = c2."msn")
)
group by c1."num", c1."msn", c1."date"
order by c1."num", c1."msn", c1."date"
See the demo.
Results:
> num | RANGEFROM | RANGETO | date
> :-- | --------: | ------: | :--------
> 1ab | 5 | 5 | 25/2/2019
> 1ab | 7 | 8 | 25/2/2019
> 1ac | 8 | 8 | 25/4/2019
> 1ad | 9 | 11 | 25/5/2019
You may try below query -
SELECT NUM, MIN(MSN), MAX(MSN), DTE
FROM (SELECT NUM, TRIM(MSN) MSN, DTE, TRIM(MSN)-ROW_NUMBER() OVER(ORDER BY DTE, TRIM(MSN)) SEQNUM
FROM T)
GROUP BY NUM, SEQNUM, DTE
ORDER BY NUM;
Here is the demo1.
Here is the demo2.
I'm using sub-query factoring and I have a query that returns invoice lines, and in the end I have this final sub-query:
I've already tried Partition but without success
SELECT
COUNT(CASE WHEN PC <> 0 THEN 1 END) AS A_LINECOUNT,
SUM(CASE WHEN PC > 0 THEN NR ELSE 0 END) AS B_PRODUCTCOUNT,
COUNT(CASE WHEN ALLOW_PAY = 1 THEN 1 END) AS C_INVOICECOUNT, --- ERROR
SUM(CASE WHEN ALLOW_PAY = 1 THEN MISSING_VALUE ELSE 0 END) AS D_INVOICETOTAL, --- ERROR
COUNT(CASE WHEN IS_NON_LIQUIDABLE_PRODUCT = 1 THEN 1 END) AS E_CONDITIONCOUNT,
COUNT(CASE WHEN IS_LIQUIDABLE_PRODUCT = 1 THEN 1 END) AS F_CONDITIONCOUNT
FROM MAIN_Q
The calculation of C_INVOICECOUNT and D_INVOICETOTAL is not correct because their values are repeated within each line of the invoice. Please consider that um MAIN_Q i also have a document_id where i can group by.
thanks
Maybe I understood correctly, maybe not, but this is too long for comment. If yes, C_INVOICECOUNT can be count as:
count(distinct case when allow_pay = 1 then document_id end)
But the problem is with D_INVOICETOTAL. You have repeated values for each invoice here and details which do not repeat. If so, add row numbering to your query:
select main_q.*, row_number() over (partition by document_id) rn from main_q
and then in problematic places use rn = 1:
select ...
count(case when rn = 1 and allow_pay = 1 then 1 end),
sum(case when rn = 1 and allow_pay = 1 then missing_value else 0 end)
...
from (select main_q.*, row_number() over (partition by document_id) rn from main_q)
Only first rows for each invoice will be analysed. Of course you can add row_number in earlier step.
I have a table like this:
col | status
----+-------
1 | 0
1 | 1
2 | 1
2 | 2
3 | 1
3 | 0
I want to select only the row with having max status value. But also want to ignore if there is any 0 in status. So expected rows would be as follows (I am ignoring 1 and 3 for having status = 0).
col | status
----+-------
2 | 2
I only can pick the rows based on max(). But when I add another clause to filter the zero, it doesn't work.
SELECT col, max(status)
FROM my_table
WHERE
(select count(*)
from my_table t1
where t1.col = col
and status = 0) = 0
GROUP BY col;
Any guide will do for me.
Use HAVING clause:
SELECT col, MAX(STATUS)
FROM tab
GROUP BY col
HAVING SUM(CASE WHEN STATUS = 0 THEN 1 ELSE 0 END) = 0;
DBFiddle
If your minimal value for STATUS is 0 then you could use:
SELECT col, MAX(STATUS)
FROM tab
GROUP BY col
HAVING MIN(STATUS) > 0;
I'm a novice at SQL, but I'm sure rank() will serve the purpose.
select tabl.col, tabl.status from
(select col, status, rank over(status desc) as rnk
from tab where status = 0) tabl
where tabl.rnk = 1
and rownum = 1;
I have a EMP table. I need to get number of employees in each department grouped by country name = 'INDIA','USA', 'AUSTRALIA'.
For example,
DEPARTMENT | #EMPLOYEE(INDIA) | #EMPLOYEE(USA) | # EMPLOYEE(AUSTRALIA)
ACCOUNTING | 5 |2 | 3
IT | 5 |2 | 1
BUSINESS | 1 |4 | 3
I need to use Partition BY to do it. I am able to use PARTITION by to get the total count of employees for each department. But I am not able to subgroup by country name.
Please give me suggestions.
Thank you.
Consider conditional count.
SELECT DEPARTMENT,
COUNT(CASE WHEN Country = 'INDIA' THEN 1 END) as emp_india,
COUNT(CASE WHEN Country = 'USA' THEN 1 END) as emp_usa,
COUNT(CASE WHEN Country = 'AUSTRALIA' THEN 1 END) as emp_australia
GROUP BY DEPARTMENT