Trouble with SQL request - sql

I just want to output only those records, that for the same name customer_name have cust_valid= 'I' and cust_valid='A'
I tried to do this, but the rezult for cust_valid have only records 'A' enter code here
SELECT c.cust_first_name ||' '|| c.cust_last_name AS CUSTOMER_NAME,
to_number(SUBSTR(c.cust_income_level, INSTR(c.cust_income_level, '-')+2), '999999') as UPPER_INCOME_LEVEL,
sum(s.amount_sold) as TOTAL_AMOUNT,
(CASE WHEN c.cust_credit_limit <= 1500 THEN 'Low_limit'
ELSE 'High_limit'
END) credit_limit_level,
c.cust_valid
FROM SH.customers c
JOIN sh.sales s on c.cust_id = s.cust_id
WHERE c.cust_valid = 'A' AND c.cust_income_level like '%-%'
GROUP BY c.cust_first_name, c.cust_last_name, c.cust_income_level, c.cust_credit_limit, c.cust_valid
HAVING SUM(s.amount_sold) > (c.cust_credit_limit * 50)
ORDER BY UPPER_INCOME_LEVEL DESC, CUSTOMER_NAME;

You need to use the EXISTS clause in WHERE condition as follows:
and exists (select 1
from sh.customers cin
where cin.cust_id = c.cust_id
and c.c.cust_valid = 'I'
)

If I followed you correctly, you can implement this filtering by modifying your having clause:
HAVING
SUM(s.amount_sold) > (c.cust_credit_limit * 50)
AND MAX(CASE WHEN cust_valid= 'I' THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN cust_valid= 'A' THEN 1 ELSE 0 END) = 1
and cust_valid='A'

I tried, but no result.
I dont think I showed the condition correct.
I have to explain...
Modify the query to display the name of the client (CUSTOMER_NAME)
for which there are rows with CUST_VALID = ā€˜Aā€™ and rows with
CUST_VALID = ā€˜Iā€™ as a separate result.

Related

Nested CASE statements in SQL

I am running the below SQL and I need to add a case statement for the svcState column.
I have a value defined for each number in that column which I need to have in my query. For instance 7 is OK, 4 is down etc. I tried adding this in the CASE statement as below and it seems, the syntax is incorrect. Any help will be greatly appreciated.
SELECT * FROM
(
SELECT
A.NodeName AS NodeName,
MAX(CASE WHEN Poller_Name='svcServiceName' THEN CAST(Status AS varchar) ELSE ''END) svcServiceName,
MAX(CASE (CASE WHEN Poller_Name='svcState' AND Status ='7' THEN 'OK'
WHEN Poller_Name='svcstate' AND Status ='4' THEN 'OUT OF SERVICE' END)
THEN CAST(Status AS bigint) ELSE '' END) svcState
FROM
(
SELECT
Nodes.Caption AS NodeName, CustomNodePollers_CustomPollers.UniqueName AS Poller_Name, CustomNodePollerStatus_CustomPollerStatus.Status AS Status, CustomNodePollerStatus_CustomPollerStatus.rowid as row, CustomNodePollerStatus_CustomPollerStatus.RawStatus as RawStatus
FROM
((Nodes INNER JOIN CustomPollerAssignment CustomNodePollerAssignment_CustomPollerAssignment ON (Nodes.NodeID = CustomNodePollerAssignment_CustomPollerAssignment.NodeID)) INNER JOIN CustomPollers CustomNodePollers_CustomPollers ON (CustomNodePollerAssignment_CustomPollerAssignment.CustomPollerID = CustomNodePollers_CustomPollers.CustomPollerID)) INNER JOIN CustomPollerStatus CustomNodePollerStatus_CustomPollerStatus ON (CustomNodePollerAssignment_CustomPollerAssignment.CustomPollerAssignmentID = CustomNodePollerStatus_CustomPollerStatus.CustomPollerAssignmentID)
WHERE
(
(CustomNodePollers_CustomPollers.UniqueName = 'svcServiceName') OR
(CustomNodePollers_CustomPollers.UniqueName = 'svcState')
)
AND
(
(CustomNodePollerAssignment_CustomPollerAssignment.InterfaceID = 0)
)
and Nodes.Caption = '101'
)A
GROUP BY NodeName, row
--ORDER BY svcServiceName
) B
Desired Output
MAX(CASE WHEN Poller_Name = 'svcState' THEN (CASE WHEN status = '7' THEN 'OK' ELSE 'DOWN' END) END)
Or...
MAX(CASE WHEN Poller_Name = 'svcState' AND status = '7' THEN 'OK'
WHEN Poller_Name = 'svcState' AND status = '4' THEN 'DOWN' END)
Or...
MAX(CASE WHEN Poller_Name != 'svcState' THEN NULL -- Assumes the poller_name is never NULL
WHEN status = '7' THEN 'OK'
WHEN status = '4' THEN 'DOWN'
END)
Where there is no ELSE specified, it is implicitly ELSE NULL, and NULL values are skipped by the MAX().

How to join two queries in SQL

I have two SQL queries that I want to join.
First query:
SELECT
rp_date, key_code,
sum(case when rp_id=15102 then rp_value else null end) as users_completed,
sum(case when rp_id=15108 then rp_value else null end) as users_inProgress
FROM
te_rp_pc_rate
WHERE
abc_code = 'A204'
AND organisation_id = '444-4'
AND key_ code = '#KL0560'
GROUP BY
rp_date, key_code
ORDER BY
rp_date DESC, key_code
LIMIT 100;
Second query:
SELECT
cr_date
sum(case when rp_id=23101 then rp_value else null end) AS prim_kfc
FROM
te_emk_rate
WHERE
abc_code = 'A204'
AND organisation_id = '444-4'
AND ref_value = 0
GROUP BY
cr_date
ORDER BY
cr_date DESC
LIMIT 100;
The dates (cr_date, rp_date) should be used for joining. For the first query's rp_date for the second cr_date.
The goal is to get the columns in a row for the same date. I've tried, but the results are too high.
You can put your queries into subqueries and join them. Something like this:
SELECT *
FROM (
SELECT rp_date, key_code,
sum(case when rp_id=15102 then rp_value else null end) as users_completed,
sum(case when rp_id=15108 then rp_value else null end) as users_inProgress
from te_rp_pc_rate
WHERE abc_code = 'A204'
AND organisation_id = '444-4'
AND key_ code = '#KL0560'
group by rp_date, key_code
Order By rp_date DESC, key_code
LIMIT 100;
) as q1
LEFT JOIN (
SELECT cr_date, key_code
sum(case when rp_id=23101 then rp_value else null end) as prim_kfc
from te_emk_rate
WHERE abc_code = 'A204'
AND organisation_id = '444-4'
AND ref_value = 0
group by cr_date, key_code
Order By cr_date DESC, key_code
LIMIT 100;
) as q2
on q1.rp_date = q2.cr_date

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);

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