How to select counts of 1 column in 1 query - db2

I want the below queries as single query.
My intention is to get just the count where job_status = A, where job_status = A and the total.
select
WORKSTATION_NAME AS CPU,
count(*) AS TOTAL
from
MDL.JOB_HISTORY_V
where
MONTH(JOB_RUN_DATE_TIME) = 01
AND YEAR(JOB_RUN_DATE_TIME) = 2015
GROUP BY
WORKSTATION_NAME
select
WORKSTATION_NAME AS CPU,
count(*) AS SUCCESS_RUNS
from
MDL.JOB_HISTORY_V
where
JOB_STATUS = 'S'
and MONTH(JOB_RUN_DATE_TIME) = 01
AND YEAR(JOB_RUN_DATE_TIME) = 2015
GROUP BY
WORKSTATION_NAME
select
WORKSTATION_NAME AS CPU,
count(*) AS ABEND_RUNS
from
MDL.JOB_HISTORY_V
where
JOB_STATUS = 'A'
and MONTH(JOB_RUN_DATE_TIME) = 01
AND YEAR(JOB_RUN_DATE_TIME) = 2015
GROUP BY
WORKSTATION_NAME

You can count with conditions as in:
select WORKSTATION_NAME AS CPU
, count(*) AS TOTAL
, count(case when JOB_STATUS = 'S' then 1 end) as SUCCESS_RUNS
, count(case when JOB_STATUS = 'A' then 1 end) as ABEND_RUNS
from MDL.JOB_HISTORY_V
where MONTH(JOB_RUN_DATE_TIME) = 01
AND YEAR(JOB_RUN_DATE_TIME) = 2015
GROUP BY WORKSTATION_NAME

Related

How to join on condition count

I have two tables. First one has id with versions:
Fid start_dt end_dt text
1 2021-09-01 00:00:00 2021-10-09 23:59:59 first_row
1 2021-10-10 00:00:00 2999-12-12 23:59:59 second_row
2 2021-10-02 00:00:00 2999-12-12 23:59:59 third_row
3 2021-09-05 00:00:00 2021-09-06 23:59:59 fourth_row
3 2021-09-07 00:00:00 2999-12-12 23:59:59 fifth_row
And second table with calls:
id dt Fid
1 2021-09-01 05:00:00 1
2 2021-10-01 18:00:00 2
3 2021-10-11 05:00:00 1
4 2021-10-01 16:50:00 2
The desired result is
id text
1 first_row
2 third_row
3 second_row
4 third_row
I want this script for rows in t1 which have several versions
select id,text
from t2
left join t1 on t1.Fid = t2.Fid and t2.dt between t1.start_dt and t1.end_dt
And this script for rows in t1 which have one version
select id,text
from t2
left join t1 on t1.Fid = t2.Fid and t2.dt between t1.start_dt and t1.end_dt
How to do this? I thought about setting to the row flag depending on the number of versions, but maybe there is an easier way?
You can do (Fiddle)
with x as (select fid,count(*) as qty from tb1 group by fid)
select tb2.id, tb1.text
from tb2 join tb1 on tb2.fid = tb1.fid and tb2.dt between tb1.start_dt and end_dt
join x on tb2.fid = x.fid and x.qty > 1
union
select tb2.id, tb1.text
from tb2 join tb1 on tb2.fid = tb1.fid
join x on tb2.fid = x.fid and x.qty = 1
order by id;

How I can find duplicate values in the result of a join operation?

I have two tables
MappingTable > Id, ItemId, Quantity
ItemTable > ItemId, Name, DateOfPurchase
I wanted to find out the duplicate rows having same Quantity and same DateOfPurchase.
eg. I have
Id ItemId Quantity
1 01 4
2 03 5
3 05 4
ItemId Name DateOfPurchase
01 AB 2019-10-30 18:30:00
05 XY 2019-10-30 18:17:00
Result:
Quantity DateOfPurchase Name
4 2019-10-30 AB
4 2019-10-30 XY
So, I might join these tables and then find duplicates
How can I do that?
One option is to use window funtions, if your database supports them:
select *
from (
select
m.*,
i.name,
i.dateOfPurchase,
count(*) over(partition by m.quantity, p.dateOfPurchase) cnt
from mapping m
inner join item i on i.itemId = m.itemId
) t
where cnt > 1
order by quantity, dateOfPurchase

PostgreSQL- get records with unique column combination

I want to select the records that have a unique column combination in postgresql, however it doesn't seem to work with distinct as distinct only removes duplicates.
Example
ID A B
01 1 2
02 1 2
03 1 3
04 2 4
05 1 4
06 2 4
07 2 5
08 1 3
In this example row with ID 05 and 07 have unique combination AB, how can i get these records
SELECT ...
With NOT EXISTS:
select t.* from tablename t
where not exists (
select 1 from tablename
where id <> t.id and a = t.a and b = t.b
)
Or with COUNT() window function:
select t.id, t.a, t.b
from (
select *, count(id) over (partition by a, b) counter
from tablename
) t
where t.counter = 1
Or with aggregation:
select max(id) id, a, b
from tablename
group by a, b
having count(id) = 1
Or with a self LEFT join that excludes the matching rows:
select t.*
from tablename t left join tablename tt
on tt.id <> t.id and tt.a = t.a and tt.b = t.b
where tt.id is null
See the demo.
Results:
| id | a | b |
| --- | --- | --- |
| 05 | 1 | 4 |
| 07 | 2 | 5 |

Select dates missing data in a range

I have a postgres table test_table that looks like this:
date | test_hour
------------+-----------
2000-01-01 | 1
2000-01-01 | 2
2000-01-01 | 3
2000-01-02 | 1
2000-01-02 | 2
2000-01-02 | 3
2000-01-02 | 4
2000-01-03 | 1
2000-01-03 | 2
I need to select all the dates which don't have test_hour = 1, 2, and 3, so it should return
date
------------
2000-01-03
Here is what I have tried:
SELECT date FROM test_table WHERE test_hour NOT IN (SELECT generate_series(1,3));
But that only returns dates that have extra hours beyond 1, 2, 3
You can use aggregation and conditional HAVING clauses, like so:
SELECT mydate
FROM mytable
GROUP BY mydate
HAVING
MAX(CASE WHEN test_hour = 1 THEN 1 END) != 1
OR MAX(CASE WHEN test_hour = 2 THEN 1 END) != 1
OR MAX(CASE WHEN test_hour = 3 THEN 1 END) != 1
Another possibility would be to join it against the series (or another subquery containing the hours) and do a [distinct] count on the hours aggregatet per date:
select date from tst
inner join (select generate_series(1,3) "hour") hours on hours.hour = tst.hour
group by tst.date
having count(distinct tst.hour) < 3;
or
select date from tst
where hour in (select generate_series(1,3))
group by date
having count(distinct tst.hour) < 3;
[You don't need the distinct if date/hour combinations in Your table are unique]
A solution using set difference, giving you exactly the rows that are missing:
(SELECT DISTINCT
date, all_hour
FROM test_table
CROSS JOIN generate_series(1,3) all_hour)
EXCEPT
(TABLE test_table)
And a solution using an array aggregate and the array contains operator:
SELECT date
FROM test_table
GROUP BY date
HAVING NOT array_agg(test_hour) #> ARRAY(SELECT generate_series(1,3))
(online demos)

Sum(Case when) resulting in multiple rows of the selection

I have a huge table of customer orders and I want to run one query to list orders by month for the past 13 months by 'user_id'. What I have now (below) works but instead of only listing one row per user_id it lists one row for each order the user_id has. Ex: one user has 42 total orders over his life with us so it lists his user_id in 42 rows and each row only has one payment. Typically I would just throw this in a pivot table in excel but I'm over the million row limit so I need for it to be right and have had zero success. I would like for the read out to look like this:
user_id | jul_12 | aug_12 |
123456 | 150.00 | 150.00 |
Not this:
user_id | jul_12 | aug_12 |
123456 | 0.00 | 150.00 |
123456 | 150.00 | 0.00 |
etc. 40 more rows
SELECT ui.user_id,
SUM(CASE WHEN date_part('year', o.time_stamp) = 2012 AND date_part('month', o.time_stamp) = 07 THEN o.amount ELSE 0 END) jul_12,
SUM(CASE WHEN date_part('year', o.time_stamp) = 2012 AND date_part('month', o.time_stamp) = 08 THEN o.amount ELSE 0 END) aug_12,
FROM orders o JOIN users_info ui ON ui.user_id = o.user_id
WHERE user_id = '123456'
GROUP BY ui.user_id, o.time_stamp;
Try something like:
SELECT ui.user_id,
SUM(CASE WHEN date_part('year', o.time_stamp) = 2012 AND date_part('month', o.time_stamp) = 07 THEN o.amount ELSE 0 END) jul_12,
SUM(CASE WHEN date_part('year', o.time_stamp) = 2012 AND date_part('month', o.time_stamp) = 08 THEN o.amount ELSE 0 END) aug_12,
FROM orders o JOIN users_info ui ON ui.user_id = o.user_id
WHERE user_id = '123456'
GROUP BY ui.user_id;
You were getting one row per order because you were grouping by o.time_stamp and timestamps are different for each order.
A shorter version of query:
SELECT ui.user_id,
SUM(CASE WHEN date_trunc('month', o.time_stamp) = to_date('2012 07','YYYY MM') THEN o.amount END) jul_12,
SUM(CASE WHEN date_trunc('month', o.time_stamp) = to_date('2012 08','YYYY MM') THEN o.amount END) aug_12,
FROM orders o
JOIN users_info ui ON ui.user_id = o.user_id
WHERE ui.user_id = '123456'
GROUP BY ui.user_id;