count case with multiple conditions in same row - sql

I need to export data of status from s.status column like
select s.name,
count(CASE WHEN s.STATUS = 'Active' THEN 1 END) AS Active_count,
count(CASE WHEN s.STATUS = 'Expired' THEN 1 END) AS Expired_count,
count(CASE WHEN s.STATUS = 'In Progress' THEN 1 END) AS InProgress_count
from my.table s
group by s.name,s.status
I expect it to be counted in one row but instead I am getting smthing like this
https://i.stack.imgur.com/K4wyc.png
Can anyone help me write it so I can get the data in one row ?
Thank you

Remove s.status from your group by

Related

HAVING gives me "column...does not exist" but I see the column

This is a practice question from stratascratch and I'm literally stuck at the final HAVING statement.
Problem statement:
Find the total number of downloads for paying and non-paying users by date. Include only records where non-paying customers have more downloads than paying customers. The output should be sorted by earliest date first and contain 3 columns date, non-paying downloads, paying downloads.
There are three tables:
ms_user_dimension (user_id, acc_id)
ms_acc_dimension (acc_id, paying_customer)
ms_download_facts (date, user_id, downloads)
This is my code so far
SELECT date,
SUM(CASE WHEN paying_customer = 'no' THEN cnt END) AS no,
SUM(CASE WHEN paying_customer = 'yes' THEN cnt END) AS yes
FROM (
SELECT date, paying_customer, SUM(downloads) AS cnt
FROM ms_download_facts d
LEFT JOIN ms_user_dimension u ON d.user_id = u.user_id
LEFT JOIN ms_acc_dimension a ON u.acc_id = a.acc_id
GROUP BY 1, 2
ORDER BY 1, 2
) prePivot
GROUP BY date
HAVING no > yes;
If I remove the HAVING no > yes at the end, the code will run and I can see I have three columns: date, yes, and no. However, if I add the HAVING statement, I get the error "column "no" does not exist...LINE 13: HAVING no > yes"
Can't figure out for the sake of my life what's going on here. Please let me know if anyone figures out something. TIA!
You don't need a subquery for this:
SELECT d.date,
SUM(CASE WHEN a.paying_customer = 'no' THEN d.downloads END) AS no,
SUM(CASE WHEN a.paying_customer = 'yes' THEN d.downloads END) AS yes
FROM ms_download_facts d LEFT JOIN
ms_user_dimension u
ON d.user_id = u.user_id LEFT JOIN
ms_acc_dimension a
ON u.acc_id = a.acc_id
GROUP BY d.date
HAVING SUM(CASE WHEN a.paying_customer = 'no' THEN d.downloads END) > SUM(CASE WHEN a.paying_customer = 'yes' THEN d.downloads END);
You can simplify the HAVING clause to:
HAVING SUM(CASE WHEN a.paying_customer = 'no' THEN 1 ELSE -1 END) > 0
This version assumes that paying_customer only takes on the values 'yes' and 'no'.
You may be able to simplify the query further, depending on the database you are using.
It doesn't like aliases in the having statement. Replace no with:
SUM(CASE WHEN paying_customer = 'no' THEN cnt END)
and do the similar thing for yes.
SELECT date,
SUM(CASE WHEN paying_customer = 'no' THEN cnt END) AS no,
SUM(CASE WHEN paying_customer = 'yes' THEN cnt END) AS yes
FROM (
SELECT date, paying_customer, SUM(downloads) AS cnt
FROM ms_download_facts d
LEFT JOIN ms_user_dimension u ON d.user_id = u.user_id
LEFT JOIN ms_acc_dimension a ON u.acc_id = a.acc_id
GROUP BY 1, 2
ORDER BY 1, 2
) prePivot
GROUP BY date
HAVING SUM(CASE WHEN paying_customer = 'no' THEN cnt END) > SUM(CASE WHEN paying_customer = 'yes' THEN cnt END);

How can I make two column from same table by two query

I've two query from same table but by two condition but how can I make two column for this two conditional count.
SELECT Count(*) FROM TBL_FT WHERE STATUS = 'X';
SELECT Count(*) FROM TBL_FT WHERE STATUS = 'Y' and
LOGDATE>trunc(sysdate);
You can use conditional aggregation:
SELECT
COUNT(CASE WHEN STATUS = 'X' THEN 1 END),
COUNT(CASE WHEN STATUS = 'Y' AND LOGDATE > trunc(sysdate) THEN 1 END)
FROM TBL_FT
You can also add a WHERE clause:
WHERE STATUS IN ('X', 'Y');
you can use something like this -
SELECT SUM(CASE
WHEN STATUS = 'X' THEN
1
ELSE
0
END) FIRST_VAL,
SUM(CASE
WHEN STATUS = 'Y'
AND LOGDATE > TRUNC(SYSDATE) THEN
1
ELSE
0
END) second_val
FROM TBL_FT;

Oracle SQL Count with join

I am trying to count Orders and Order lines dependent upon order type. So far i have counted the Order headers per order type.
SELECT lifnr,
COUNT(CASE WHEN e1.bsart = 'NB' THEN 1 ELSE NULL END) Schedule_Orders,
COUNT(CASE WHEN e1.bsart = 'ZNBS' THEN 1 ELSE NULL END) Store_Orders,
COUNT(CASE WHEN e1.bsart = 'ZCSO' THEN 1 ELSE NULL END) Third_Party,
COUNT(CASE WHEN e1.bsart NOT IN ('ZCSO', 'NB', 'ZNBS' ) THEN 1 ELSE NULL END) Other_Orders,
COUNT(*) Total_Orders
FROM saprpe.ekko e1
JOIN saprpe.ekpo p1
ON e1.ebeln = p1.ebeln
WHERE e1.aedat BETWEEN '20130701' AND '20140701'
GROUP BY lifnr
Order Lines are stored in table EKPO so i have joined EKKO to EKPO using the document number. How do i go about counting order lines for each of the order types on the case above? I've only managed to count ALL order lines, not specifically for each order type.
Extra Info: An Order header is stored in EKKO which contains a Vendor, an OrderNumber and an OrderType. EKKO has a 1-to-many relationship with table EKPO which contains Order lines. Order lines relates to Order Header through the Order Number.
What i am trying to do is get the total order headers for the three order types NB, ZNBS and ZCSO, and the total lines for each order type. All into their own columns
For example I would want to see;
Vendor1, 10 NB orders, 100 NB Order Lines, 0 ZNBS Orders, 0 ZNBS Order Lines, 5 ZCSO Orders, 15 ZCSO Order Lines, 15 Total Orders, 115 Total Order Lines
Please point out if i need to clarify anything. I should note i would prefer this in a single SQL query, i can manage it on an individual query basis for each Order Type using the WHERE clause.
After some trial and error, googling etc, I eventually got there.
SELECT
lifnr,
COUNT(DISTINCT (CASE WHEN e1.bsart = 'NB' THEN e1.ebeln ELSE NULL END)) Schedule_Orders,
COUNT(CASE WHEN e1.bsart = 'NB' THEN e1.ebeln ELSE NULL END) Schedule_Order_Lines,
COUNT(DISTINCT (CASE WHEN e1.bsart = 'ZNBS' THEN e1.ebeln ELSE NULL END)) Store_Orders,
COUNT(CASE WHEN e1.bsart = 'ZNBS' THEN e1.ebeln ELSE NULL END) Store_Order_Lines,
COUNT(DISTINCT (CASE WHEN e1.bsart = 'ZCSO' THEN e1.ebeln ELSE NULL END)) Third_Party,
COUNT(CASE WHEN e1.bsart = 'ZCSO' THEN e1.ebeln ELSE NULL END) Third_Party_Lines,
COUNT(DISTINCT (CASE WHEN e1.bsart NOT IN ('ZCSO', 'NB', 'ZNBS' ) THEN e1.ebeln ELSE NULL END)) Other_Orders,
COUNT(CASE WHEN e1.bsart NOT IN ('ZCSO', 'NB', 'ZNBS') THEN e1.ebeln ELSE NULL END) Other_Order_Lines,
COUNT(DISTINCT(e1.ebeln)) Total_Orders,
COUNT(e1.ebeln) Total_Order_Lines
FROM saprpe.ekko e1
LEFT JOIN saprpe.ekpo p1
ON e1.ebeln = p1.ebeln
WHERE e1.aedat BETWEEN '20130701' AND '20140701'
GROUP BY lifnr
The JOIN originally was making my header count the same count as the lines because of the relationship between the tables... Adding DISTINCT to my header counts and using a case for the line counts enabled me to count for those order types.

Merging data SQL Query

I have a query request where I have to show one customer activity for each web-site but it has to be only one row each, instead of one customer showing multiple times for each activity.
Following is the query I tried but brings lot more rows. please help me as how I can avoid duplicates and show only one customer by each row for each activity.
SELECT i.customer_id, i.SEGMENT AS Pistachio_segment,
(CASE when S.SUBSCRIPTION_TYPE = '5' then 'Y' else 'N' end ) PB_SUBS
(CASE WHEN S.SUBSCRIPTION_TYPE ='12' THEN 'Y' ELSE 'N' END) Daily_test,
(CASE when S.SUBSCRIPTION_TYPE ='8' then 'Y' else 'N' end) COOK_4_2
FROM IDEN_WITH_MAIL_ID i JOIN CUSTOMER_SUBSCRIPTION_FCT S
ON I.IDENTITY_ID = S.IDENTITY_ID and I.CUSTOMER_ID = S.CUSTOMER_ID
WHERE s.site_code ='PB' and s.subscription_end_date is null
Sounds like you need to group by customer_id and perform aggregations for the other columns you are selecting. For example:
sum(case when s.subscription_type = '5' then 1 else 0 end) as pb_subs_count
You could try one of two things:
Use a GROUP BY statement to combine all records with the same id, e.g.,
...
WHERE s.site_code ='PB' and s.subscription_end_date is null
GROUP BY i.customer_id
Use the DISTINCT command in your SELECT, e.g.,
SELECT DISTINCT i.customer_id, i.SEGMENT, ...
you could use a aggregation (SUM) on customer_id, but what do you expect to happen on the other fields? for example, if you have SUBSCRIPTION_TYPE 5 and 13 for the same customer (2 rows), which value do you want?
Perhaps you are looking for something like this:
SELECT i.customer_id, i.SEGMENT AS Pistachio_segment,
MAX(CASE when S.SUBSCRIPTION_TYPE = '5' then 'Y' else 'N' end ) PB_SUBS
MAX(CASE WHEN S.SUBSCRIPTION_TYPE ='12' THEN 'Y' ELSE 'N' END) Daily_test,
MAX(CASE when S.SUBSCRIPTION_TYPE ='8' then 'Y' else 'N' end) COOK_4_2
FROM IDEN_WITH_MAIL_ID i JOIN CUSTOMER_SUBSCRIPTION_FCT S
ON I.IDENTITY_ID = S.IDENTITY_ID and I.CUSTOMER_ID = S.CUSTOMER_ID
WHERE s.site_code ='PB' and s.subscription_end_date is null
GROUP BY i.customer_id, i.SEGMENT
I can't be sure, though, without knowing more about the tables involved.

SQL - How do I simplify this easy query?

I am using SQL Server 2005.
How could I refactor this query?
SELECT Total, Installs, Service, tot.ls_chg_dte_ojb
FROM (SELECT COUNT(*) [Total], ls_chg_dte_ojb
FROM [COMPL_INST_SVC]
GROUP BY ls_chg_dte_ojb) tot
JOIN (SELECT COUNT(*) [Service], ls_chg_dte_ojb
FROM [COMPL_INST_SVC]
WHERE job_class_ojb = 'S'
GROUP BY ls_chg_dte_ojb) svc on svc.ls_chg_dte_ojb = tot.ls_chg_dte_ojb
JOIN (SELECT COUNT(*) [Installs], ls_chg_dte_ojb
FROM [COMPL_INST_SVC]
WHERE job_class_ojb in ('C', 'R')
GROUP BY ls_chg_dte_ojb) ins on ins.ls_chg_dte_ojb = tot.ls_chg_dte_ojb
It looks like the Total and Service counts are counting the same exact thing, so you'll need to fix that, but here's basically how you do the counts in a simpler way:
SELECT
COUNT(CASE WHEN job_class_ojb = 'S' THEN 1 END) AS [Total],
COUNT(CASE WHEN job_class_ojb = 'S' THEN 1 END) AS [Service],
COUNT(CASE WHEN job_class_ojb in ('C', 'R') THEN 1 END) AS [Installs]
FROM
[COMPL_INST_SVC]
Two of your sub-selects are the same. Ignoring the 'Service' one, try something along the lines of
SELECT
SUM(CASE WHEN job_class_ojb = 'S' THEN 1 ELSE 0 END) as Total,
SUM(CASE WHEN job_class_ojb = 'C' or
job_class_ojb = 'R' THEN 1 ELSE 0 END) as Installs
FROM COMPL_INST_SVC
I suspect that the Totals subquery should not include the WHERE job_class_ojb = 'S' condition - if so, I suggest:
SELECT COUNT(*) Total,
SUM(CASE WHEN job_class_ojb = 'S' THEN 1 ELSE 0 END) Service,
SUM(CASE WHEN job_class_ojb in ('C','R') THEN 1 ELSE 0 END) Installs,
ls_chg_dte_ojb
FROM COMPL_INST_SVC
GROUP BY ls_chg_dte_ojb