How to display my query result vertically in postgresql? - sql

This is my SQL query and i want these results to be displayed vertically. I also searched google for this where i found to turn the toggle mode on by using \x\g\x but i don,t know where to put that syntax. Please help to get output like this:
But, my this query gives output like this:
select
round(
100.00 *
(sum(case when "WELL_AGE" <= '5' AND "CONC_ARSC" <= '10' then 1 else 0 end))/(sum(case when "WELL_AGE" <= '5' then 1 else 0 end)),1) conc_arscbelow5_wellageGrp,
round(
100.00 *
(sum(case when "WELL_AGE" >= '6' AND "WELL_AGE" <= '10' AND "CONC_ARSC" <= '10' then 1 else 0 end))/(sum(case when "WELL_AGE" >= '6' AND "WELL_AGE" <= '10' then 1 else 0 end)),1) conc_arscbet6_10wellageGrp,
round(
100.00 *
(sum(case when "WELL_AGE" >= '11' AND "WELL_AGE" <= '15' AND "CONC_ARSC" <= '10' then 1 else 0 end))/(sum(case when "WELL_AGE" >= '11' AND "WELL_AGE" <= '15' then 1 else 0 end)),1) conc_arscbet11_15_wellageGrp,
round(
100.00 *
(sum(case when "WELL_AGE" >= '16' AND "WELL_AGE" <= '30' AND "CONC_ARSC" <= '10' then 1 else 0 end))/(sum(case when "WELL_AGE" >= '16' AND "WELL_AGE" <= '30' then 1 else 0 end)),1) conc_arscbet16_30wellageGrp,
round(
100.00 *
(sum(case when "WELL_AGE" >= '31' AND "WELL_AGE" <= '50' AND "CONC_ARSC" <= '10' then 1 else 0 end))/(sum(case when "WELL_AGE" >= '31' AND "WELL_AGE" <= '50' then 1 else 0 end)),1) conc_arscbet31_50wellageGrp,
round(
100.00 *
(sum(case when "WELL_AGE" > '50' AND "CONC_ARSC" <= '10' then 1 else 0 end))/(sum(case when "WELL_AGE" > '50' then 1 else 0 end)),1 )conc_arscabove50_wellageGrp
from public."Arsenic_Test";

I hope that this will match with your requirement.
Using hstore:
with t as (SELECT '80.13' aS "0-5", '80.7' AS "6-10", '81.6' AS "11-15", '84.27' AS "16-30", '84.04' AS "31-50", '85.33' AS ">50")
SELECT *
FROM (SELECT (each(hstore(t))).* FROM t) AS tmp (well_age, below10_conc_arsc_wells)
Replace t with your table.
Using json:
with t as (SELECT '80.13' aS "0-5", '80.7' AS "6-10", '81.6' AS "11-15", '84.27' AS "16-30", '84.04' AS "31-50", '85.33' AS ">50")
SELECT *
FROM (SELECT (json_each_text(row_to_json(t))).* FROM t) AS tmp (well_age, below10_conc_arsc_wells)

Use the range type to group on:
with r (r,s) as ( values
(int4range(null,5,'[]'), '0 - 5'),
(int4range(6,10,'[]'), '6 - 10'),
(int4range(11,15,'[]'), '11 - 15'),
(int4range(16,30,'[]'), '16 - 30'),
(int4range(31,50,'[]'), '31 - 50'),
(int4range(50,null,'(]'), '>50')
)
select s, 100* count("CONC_ARSC" <= '10' or null) / count(*)
from
public."Arsenic_Test"
inner join
r on "WELL_AGE" <# r
group by s;

Related

SQL two decimal

How to make persen_sukses or persen_gagal only get 2 decimal ?
I try use round but get some error.
May be anyone can help me.
Here is my sql
SELECT * ,(CASE WHEN all_trx.trx_gagal = 0 THEN 100 WHEN all_trx.trx_sukses = 0 THEN 0 ELSE (CAST(all_trx.trx_sukses AS float)/CAST(all_trx.trx_total AS float)*100) END) AS persen_sukses,
(CASE WHEN all_trx.trx_sukses = 0 THEN 100 WHEN all_trx.trx_gagal = 0 THEN 0 ELSE (CAST(all_trx.trx_gagal AS float)/CAST(all_trx.trx_total AS float)*100) END) AS persen_gagal
FROM
(SELECT kode_produk AS Produk,
COUNT(CASE WHEN status = '20' THEN 1 END) AS trx_sukses,
COUNT(CASE WHEN status > '20' THEN 1 END) AS trx_gagal,
COUNT(CASE WHEN status >= '20' THEN 1 END) AS trx_total
FROM transaksi WHERE CAST(tgl_entri AS DATE) = CAST(GETDATE() AS DATE) GROUP BY kode_produk)
AS all_trx
SELECT *
,(CASE
WHEN all_trx.trx_gagal = 0 THEN 100
WHEN all_trx.trx_sukses = 0 THEN 0
--ELSE (CAST(all_trx.trx_sukses AS float)/CAST(all_trx.trx_total AS float)*100)
ELSE CAST(all_trx.trx_sukses*100.0 / all_trx.trx_total as numeric(18,2) )
END) AS persen_sukses
,(CASE
WHEN all_trx.trx_sukses = 0 THEN 100
WHEN all_trx.trx_gagal = 0 THEN 0
--ELSE (CAST(all_trx.trx_gagal AS float)/CAST(all_trx.trx_total AS float)*100)
ELSE CAST(all_trx.trx_gagal*100.0 / all_trx.trx_total as numeric(18,2) )
END) AS persen_gagal
FROM
(
SELECT
kode_produk AS Produk,
COUNT(CASE WHEN status = '20' THEN 1 END) AS trx_sukses,
COUNT(CASE WHEN status > '20' THEN 1 END) AS trx_gagal,
COUNT(CASE WHEN status >= '20' THEN 1 END) AS trx_total
FROM transaksi
WHERE CAST(tgl_entri AS DATE) = CAST(GETDATE() AS DATE)
GROUP BY kode_produk
) AS all_trx
Dear i am able to fix the issue in your query, Pleae note the only change i did is ELSE part of Case Statement. I executed the query and now returning the value upto two decimal places only. If you have to increase or decrease the digits after the decimal sign update the value of numeric(18,2) here 2 is number of digit after decimal.

Sum Every N Records SQL

I have this query, which returns (Right Below 'Query Results') a grouped date(varchar), and some values.
They are vehicles that have passed by toll plazas.
SELECT SUBSTR(CAB_MOMENTO,1,12),
Sum(CASE WHEN COMVSAUTO = '1' AND NOME IN ('SUL','OESTE') THEN 1 ELSE 0 END)
SUL_OESTE_AUTO,
Sum(CASE WHEN COMVSAUTO = '0' AND NOME IN ('SUL','OESTE') THEN 1 ELSE 0 END)
SUL_OESTE_COM,
Sum(CASE WHEN COMVSAUTO = '1' AND NOME IN ('NORTE','LESTE') THEN 1 ELSE 0
END) NORTE_LESTE_AUTO,
Sum(CASE WHEN COMVSAUTO = '0' AND NOME IN ('NORTE','LESTE') THEN 1 ELSE 0
END) NORTE_LESTE_COM FROM
(SELECT a.idtransaccion, a.cab_momento, a.cab_via, a.comvsauto, b.NOME
FROM
(select idtransaccion, cab_momento, cab_via, cab_estacion AS ESTACION,
CASE ctl_clase
WHEN '01' THEN 1
WHEN '07' THEN 1
WHEN '08' THEN 1
ELSE 0
END comvsauto
FROM usrhost.atransaccion
WHERE cab_momento > '20170818000000') a
INNER join
(SELECT sen.estacion AS ESTACION, via.via AS VIA, sen.nome AS NOME FROM
usrhost.aestacion_sentido sen
INNER JOIN usrhost.avia via ON
sen.estacion = via.estacion
AND SubStr(via.via,3,1) = sen.sentido
ORDER BY 1,2) b ON
b.VIA = a.cab_via
AND b.ESTACION = a.ESTACION)
GROUP BY SUBSTR(CAB_MOMENTO,1,12)
ORDER BY 1
I need the sum every 15 minutes (1st column).
For example:
From minute X to Minute Y - 1231 | 12314 | 1241 | 21415
From minute X+15 to Minute Y+15 - 1111 | 13344 | 1345 | 22455
...
Thank You In Advance
Work it! Thank you very much.
SELECT SubStr(CAB_MOMENTO,1,10) ||' '||
CASE WHEN To_Number(SubStr(cab_momento,11,2)) < 15 THEN '00-15'
WHEN To_Number(SubStr(cab_momento,11,2)) < 30 THEN '15-30'
WHEN To_Number(SubStr(cab_momento,11,2)) < 45 THEN '30-45'
ELSE '45-00'
END As time_period, Sum(sul_oeste_auto),
Sum(sul_oeste_com),Sum(norte_leste_auto), Sum(norte_leste_com)
FROM (
SELECT SUBSTR(CAB_MOMENTO,1,12) AS cab_momento,
Sum(CASE WHEN COMVSAUTO = '1' AND NOME IN ('SUL','OESTE') THEN 1 ELSE 0 END)
SUL_OESTE_AUTO,
Sum(CASE WHEN COMVSAUTO = '0' AND NOME IN ('SUL','OESTE') THEN 1 ELSE 0 END)
SUL_OESTE_COM,
Sum(CASE WHEN COMVSAUTO = '1' AND NOME IN ('NORTE','LESTE') THEN 1 ELSE 0
END) NORTE_LESTE_AUTO,
Sum(CASE WHEN COMVSAUTO = '0' AND NOME IN ('NORTE','LESTE') THEN 1 ELSE 0
END) NORTE_LESTE_COM FROM
(SELECT a.idtransaccion, a.cab_momento, a.cab_via, a.comvsauto, b.NOME
FROM
(select idtransaccion, cab_momento, cab_via, cab_estacion AS ESTACION,
CASE ctl_clase
WHEN '01' THEN 1
WHEN '07' THEN 1
WHEN '08' THEN 1
ELSE 0
END comvsauto
FROM usrhost.atransaccion
WHERE cab_momento > '20170818000000') a
INNER join
(SELECT sen.estacion AS ESTACION, via.via AS VIA, sen.nome AS NOME FROM
usrhost.aestacion_sentido sen
INNER JOIN usrhost.avia via ON
sen.estacion = via.estacion
AND SubStr(via.via,3,1) = sen.sentido
ORDER BY 1,2) b ON
b.VIA = a.cab_via
AND b.ESTACION = a.ESTACION)
GROUP BY SUBSTR(CAB_MOMENTO,1,12)
ORDER BY 1)
GROUP BY SubStr(CAB_MOMENTO,1,10),CASE WHEN
To_Number(SubStr(cab_momento,11,2)) < 15 THEN '00-15'
WHEN To_Number(SubStr(cab_momento,11,2)) < 30 THEN '15-30'
WHEN To_Number(SubStr(cab_momento,11,2)) < 45 THEN '30-45'
ELSE '45-00'
END
ORDER BY 1
You can use the expression below to give you a datetime with the minutes adjusted to quarter hours. This will give you the ability to easily group to times and dates.
CONVERT(datetime, LEFT(CONVERT(varchar(30), cab_momento, 126), 14) + RIGHT('0' + CONVERT(varchar(2), DATEPART(MINUTE, cab_momento) / 15 * 15), 2) + ':00.000', 126)

SQL Query to MS Access Query

I have a section of SQL code that can be run to show age buckets of a particular workload. Due to some system changes i will soon not be able to access this database through SQL and I do not really follow it.
please can someone help me convert this into an MS Access Query, I have included the SQL and Results below,
SQL
Use MoxieApp
select
b.mailboxid,
b.Name as 'Mailbox',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) <= '1' THEN 1 ELSE 0 END) as '1',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '1' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '2' THEN 1 ELSE 0 END) as '2',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '2' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '3' THEN 1 ELSE 0 END) as '3',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '3' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '4' THEN 1 ELSE 0 END) as '4',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '4' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '5' THEN 1 ELSE 0 END) as '5',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '5' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '6' THEN 1 ELSE 0 END) as '6',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '6' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '7' THEN 1 ELSE 0 END) as '7',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '7' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '8' THEN 1 ELSE 0 END) as '8',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '8' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '9' THEN 1 ELSE 0 END) as '9',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '9' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '10' THEN 1 ELSE 0 END) as '10',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '10' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '11' THEN 1 ELSE 0 END) as '11',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '11' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '12' THEN 1 ELSE 0 END) as '12',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '12' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '13' THEN 1 ELSE 0 END) as '13',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '13' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '14' THEN 1 ELSE 0 END) as '14',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '14' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '15' THEN 1 ELSE 0 END) as '15',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '15' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '16' THEN 1 ELSE 0 END) as '16',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '16' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '17' THEN 1 ELSE 0 END) as '17',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '17' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '18' THEN 1 ELSE 0 END) as '18',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '18' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '19' THEN 1 ELSE 0 END) as '19',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '19' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '20' THEN 1 ELSE 0 END) as '20',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '20' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '21' THEN 1 ELSE 0 END) as '21',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '21' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '22' THEN 1 ELSE 0 END) as '22',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '22' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '23' THEN 1 ELSE 0 END) as '23',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '23' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '24' THEN 1 ELSE 0 END) as '24',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '24' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '48' THEN 1 ELSE 0 END) as '48',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '48' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '72' THEN 1 ELSE 0 END) as '72',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '72' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '96' THEN 1 ELSE 0 END) as '96',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '96' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '120' THEN 1 ELSE 0 END) as '120',
SUM(case when datediff(hh,a.DateRecv,GETUTCDATE()) > '120' and datediff(hh,a.DateRecv,GETUTCDATE()) <= '10000' THEN 1 ELSE 0 END) as 'Greater'
from mailmessage a
left outer join mailbox b on a.origmailboxid = b.mailboxid
where a.routedate > '2015-04-21'
and a.status = '0'
and b.MailBoxID IN ('163')
group by name,mailboxid
select mailboxid, name from mailbox
Results
163 Mailbox Name 39 16 9 8 4 2 1 2 4 2 2 7 9 5 14 18 18 12 9 4 2 3 0 0 2 3 2 0 1
I would really appreciate some help with this! Thanks in advance
Here is an example of how you can do the date arithmetic:
SUM(iif(datediff("h", a.DateRecv, now()) > 1 and datediff("h", a.DateRecv, now()) <= 2, 1, 0)) as [2]
However, this doesn't handle the GETUTCDATE() issue. If NOW() doesn't work for you (for some reason), then calculate the value you want and pass it into the query.

Select data grouped by time over midnight

I have a table like:
ID TIMEVALUE
----- -------------
1 06.07.15 06:43:01,000000000
2 06.07.15 12:17:01,000000000
3 06.07.15 18:21:01,000000000
4 06.07.15 23:56:01,000000000
5 07.07.15 04:11:01,000000000
6 07.07.15 10:47:01,000000000
7 07.07.15 12:32:01,000000000
8 07.07.15 14:47:01,000000000
and I want to group this data by special times.
My current query looks like this:
SELECT TO_CHAR(TIMEVALUE, 'YYYY\MM\DD'), COUNT(ID),
SUM(CASE WHEN TO_CHAR(TIMEVALUE, 'HH24MI') <=700 THEN 1 ELSE 0 END) as morning,
SUM(CASE WHEN TO_CHAR(TIMEVALUE, 'HH24MI') >700 AND TO_CHAR(TIMEVALUE, 'HH24MI') <1400 THEN 1 ELSE 0 END) as daytime,
SUM(CASE WHEN TO_CHAR(TIMEVALUE, 'HH24MI') >=1400 THEN 1 ELSE 0 END) as evening FROM Table
WHERE TIMEVALUE >= to_timestamp('05.07.2015','DD.MM.YYYY')
GROUP BY TO_CHAR(TIMEVALUE, 'YYYY\MM\DD')
and I am getting this output
day overall morning daytime evening
----- ---------
2015\07\05 454 0 0 454
2015\07\06 599 113 250 236
2015\07\07 404 139 265 0
so that is fine grouping on the same day (0-7 o'clock, 7-14 o'clock and 14-24 o'clock)
But my question now is:
How can I group over midnight?
For example count from 6-14 , 14-23 and 23-6 o'clock on next day.
I hope you understand my question. You are welcome to even improve my upper query if there is a better solution.
EDIT: It is tested now: SQL Fiddle
The key is simply to adjust the group by so that anything before 6am gets grouped with the previous day. After that, the counts are pretty straight-forward.
SELECT TO_CHAR(CASE WHEN EXTRACT(HOUR FROM timevalue) < 6
THEN timevalue - 1
ELSE timevalue
END, 'YYYY\MM\DD') AS day,
COUNT(*) AS overall,
SUM(CASE WHEN EXTRACT(HOUR FROM timevalue) >= 6 AND EXTRACT(HOUR FROM timevalue) < 14
THEN 1 ELSE 0 END) AS morning,
SUM(CASE WHEN EXTRACT(HOUR FROM timevalue) >= 14 AND EXTRACT(HOUR FROM timevalue) < 23
THEN 1 ELSE 0 END) AS daytime,
SUM(CASE WHEN EXTRACT(HOUR FROM timevalue) < 6 OR EXTRACT(HOUR FROM timevalue) >= 23
THEN 1 ELSE 0 END) AS evening
FROM my_table
WHERE timevalue >= TO_TIMESTAMP('05.07.2015','DD.MM.YYYY')
GROUP BY TO_CHAR(CASE WHEN EXTRACT(HOUR FROM timevalue) < 6
THEN timevalue - 1
ELSE timevalue
END, 'YYYY\MM\DD');
Substract 1 day from timevalue for times lower than '06:00' at first and then:
SQLFiddle demo
select TO_CHAR(day, 'YYYY\MM\DD') day, COUNT(ID) cnt,
SUM(case when '23' < tvh or tvh <= '06' THEN 1 ELSE 0 END) as midnight,
SUM(case when '06' < tvh and tvh <= '14' THEN 1 ELSE 0 END) as daytime,
SUM(case when '14' < tvh and tvh <= '23' THEN 1 ELSE 0 END) as evening
FROM (
select id, to_char(TIMEVALUE, 'HH24') tvh,
trunc(case when (to_char(timevalue, 'hh24') <= '06')
then timevalue - interval '1' day
else timevalue end) day
from t1
)
GROUP BY day
Maybe you can do it like this (with some reformatting or PIVOT):
WITH spans AS
(SELECT TIMESTAMP '2015-01-01 00:00:00' + LEVEL * INTERVAL '1' HOUR AS start_time
FROM dual
CONNECT BY TIMESTAMP '2015-01-01 00:00:00' + LEVEL * INTERVAL '1' HOUR < LOCALTIMESTAMP),
t AS
(SELECT start_time, lead(start_time, 1) OVER (ORDER BY start_time) AS end_time, ROWNUM AS N
FROM spans
WHERE EXTRACT(HOUR FROM start_time) IN (6,14,23))
SELECT N, start_time, end_time, COUNT(*) AS ID_COUNT,
DECODE(EXTRACT(HOUR FROM start_time), 6,'morning', 14,'daytime', 23,'evening') AS daytime
FROM t
JOIN YOUR_TABLE WHERE TIMEVALUE BETWEEN start_time AND end_time
GROUP BY N;
Of course, the initial time value ('2015-01-01 00:00:00' in my example) has to be lower than the least date in your table.

Including a row in the result of a SELECT for which the select didnt recover any data

I'm trying write a query to retrieve the following data :
TYPE | TOTAL | 0_10 DAYS | 10_20 DAYS | .......
X 300 100 200 .......
Y 0 0 0 .......
Z 600 50 120 .......
I have to group all my entries by type and count the number of entries of each type for each date range and add them up as a total.
My problem is the need to display rows of zeros for the types for which I don't retrieve any data. Basically the type column always displays a fixed amount of types. So far I have tried using 'UNION ALL' but then the rows of zeros will always show. Here is my query :
SELECT TYPE AS "ORDERS",
Count(*) AS "TOTAL",
Nvl(Sum(CASE
WHEN ( DATE_ORDER BETWEEN SYSDATE - 10 AND SYSDATE ) THEN 1
ELSE 0
END), 0) AS "0_10_DAYS",
Nvl(Sum(CASE
WHEN ( DATE_ORDER BETWEEN SYSDATE - 20 AND SYSDATE - 11 ) THEN
1
ELSE 0
END), 0) AS "10_20_DAYS",
Nvl(Sum(CASE
WHEN ( DATE_ORDER BETWEEN SYSDATE - 30 AND SYSDATE - 21 ) THEN
1
ELSE 0
END), 0) AS "20_30_DAYS",
Nvl(Sum(CASE
WHEN ( DATE_ORDER <= To_date(SYSDATE - 30) ) THEN 1
ELSE 0
END), 0) AS "PLUS_30_DAYS"
FROM T_ORDERS
WHERE TYPE = 'X'
OR TYPE = 'Y'
OR TYPE = 'Z'
GROUP BY TYPE
UNION ALL
SELECT TYPE AS "ORDERS",
0 AS "TOTAL",
0 AS "0_10_DAYS",
0 AS "10_20_DAYS",
0 AS "20_30_DAYS",
0 AS "PLUS_30_DAYS"
FROM T_ORDERS
WHERE TYPE IS NOT NULL
GROUP BY TYPE;
I'm new to SQL so bear with me if any of the answers to questions on this topic solves mine but I can't seem to work it out. If something is unclear please write it in comment box.
Try:
SELECT TYPE AS "ORDERS",
Count(DATE_ORDER) AS "TOTAL",
Nvl(Sum(CASE
WHEN (DATE_ORDER BETWEEN SYSDATE - 10 AND SYSDATE) THEN 1
ELSE 0
END), 0) AS "0_10_DAYS",
Nvl(Sum(CASE
WHEN (DATE_ORDER BETWEEN SYSDATE - 20 AND SYSDATE - 11) THEN 1
ELSE 0
END), 0) AS "10_20_DAYS",
Nvl(Sum(CASE
WHEN (DATE_ORDER BETWEEN SYSDATE - 30 AND SYSDATE - 21) THEN 1
ELSE 0
END), 0) AS "20_30_DAYS",
Nvl(Sum(CASE
WHEN (DATE_ORDER <= To_date(SYSDATE - 30)) THEN 1
ELSE 0
END), 0) AS "PLUS_30_DAYS"
FROM (SELECT TYPE, DATE_ORDER
FROM T_ORDERS
WHERE TYPE IN ('X', 'Y', 'Z')
UNION ALL
SELECT DECODE(LEVEL, 1,'X', 2,'Y', 3,'Z') TYPE, NULL DATE_ORDER
FROM DUAL
CONNECT BY LEVEL <= 3
) SQ
GROUP BY TYPE
you can use an OUTER JOIN to achive the desired result
with types
AS
(
SELECT 'X' as t_name FROM dual
UNION ALL
SELECT 'Y' as t_name FROM dual
UNION ALL
SELECT 'Z' as t_name FROM dual
)
SELECT
types.t_name AS "ORDERS",
SUM(CASE WHEN T_ORDERS.TYPE IS NULL THEN 0 ELSE 1 END ) AS "TOTAL",
Nvl(Sum(CASE
WHEN ( DATE_ORDER BETWEEN SYSDATE - 10 AND SYSDATE ) THEN 1
ELSE 0
END), 0) AS "0_10_DAYS",
Nvl(Sum(CASE
WHEN ( DATE_ORDER BETWEEN SYSDATE - 20 AND SYSDATE - 11 ) THEN
1
ELSE 0
END), 0) AS "10_20_DAYS",
Nvl(Sum(CASE
WHEN ( DATE_ORDER BETWEEN SYSDATE - 30 AND SYSDATE - 21 ) THEN
1
ELSE 0
END), 0) AS "20_30_DAYS",
Nvl(Sum(CASE
WHEN ( DATE_ORDER <= To_date(SYSDATE - 30) ) THEN 1
ELSE 0
END), 0) AS "PLUS_30_DAYS"
FROM
types
LEFT OUTER JOIN T_ORDERS ON (types.t_name = T_ORDERS.TYPE )
GROUP BY types.t_name
or if you already have all types in a TYPES table you can use this table instead of WITH
SELECT
types.t_name AS "ORDERS",
SUM(CASE WHEN T_ORDERS.TYPE IS NULL THEN 0 ELSE 1 END ) AS "TOTAL",
Nvl(Sum(CASE
WHEN ( DATE_ORDER BETWEEN SYSDATE - 10 AND SYSDATE ) THEN 1
ELSE 0
END), 0) AS "0_10_DAYS",
Nvl(Sum(CASE
WHEN ( DATE_ORDER BETWEEN SYSDATE - 20 AND SYSDATE - 11 ) THEN
1
ELSE 0
END), 0) AS "10_20_DAYS",
Nvl(Sum(CASE
WHEN ( DATE_ORDER BETWEEN SYSDATE - 30 AND SYSDATE - 21 ) THEN
1
ELSE 0
END), 0) AS "20_30_DAYS",
Nvl(Sum(CASE
WHEN ( DATE_ORDER <= To_date(SYSDATE - 30) ) THEN 1
ELSE 0
END), 0) AS "PLUS_30_DAYS"
FROM
types
LEFT OUTER JOIN T_ORDERS ON (types.t_name = T_ORDERS.TYPE )
WHERE
types.t_name IN ( 'X', 'Y','Z')
GROUP BY types.t_name