SQL Nested Select statements with COUNT() - sql

I'll try to describe as best I can, but it's hard for me to wrap my whole head around this problem let alone describe it....
I am trying to select multiple results in one query to display the current status of a database. I have the first column as one type of record, and the second column as a sub-category of the first column. The subcategory is then linked to more records underneath that, distinguished by status, forming several more columns. I need to display every main-category/subcategory combination, and then the count of how many of each sub-status there are beneath that subcategory in the subsequent columns. I've got it so that I can display the unique combinations, but I'm not sure how to nest the select statements so that I can select the count of a completely different table from the main query. My problem lies in that to display the main category and sub category, I can pull from one table, but I need to count from a different table. Any ideas on the matter would be greatly appreciated
Here's what I have. The count statements would be replaced with the count of each status:
SELECT wave_num "WAVE NUMBER",
int_tasktype "INT / TaskType",
COUNT (1) total,
COUNT (1) "LOCKED/DISABLED",
COUNT (1) released,
COUNT (1) "PARTIALLY ASSEMBLED",
COUNT (1) assembled
FROM (SELECT DISTINCT
(t.invn_need_type || ' / ' || s.code_desc) int_tasktype,
t.task_genrtn_ref_nbr wave_num
FROM sys_code s, task_hdr t
WHERE t.task_genrtn_ref_nbr IN
(SELECT ship_wave_nbr
FROM ship_wave_parm
WHERE TRUNC (create_date_time) LIKE SYSDATE - 7)
AND s.code_type = '590'
AND s.rec_type = 'S'
AND s.code_id = t.task_type),
ship_wave_parm swp
GROUP BY wave_num, int_tasktype
ORDER BY wave_num
Image here: http://i.imgur.com/JX334.png

Guessing a bit,both regarding your problem and Oracle (which I've - unfortunately - never used), hopefully it will give you some ideas. Sorry for completely messing up the way you write SQL, SELECT ... FROM (SELECT ... WHERE ... IN (SELECT ...)) simply confuses me, so I have to restructure:
with tmp(int_tasktype, wave_num) as
(select distinct (t.invn_need_type || ' / ' || s.code_desc), t.task_genrtn_ref_nbr
from sys_code s
join task_hdr t
on s.code_id = t.task_type
where s.code_type = '590'
and s.rec_type = 'S'
and exists(select 1 from ship_wave_parm p
where t.task_genrtn_ref_nbr = p.ship_wave_nbr
and trunc(p.create_date_time) = sysdate - 7))
select t.wave_num "WAVE NUMBER", t.int_tasktype "INT / TaskType",
count(*) TOTAL,
sum(case when sst.sub_status = 'LOCKED' then 1 end) "LOCKED/DISABLED",
sum(case when sst.sub_status = 'RELEASED' then 1 end) RELEASED,
sum(case when sst.sub_status = 'PARTIAL' then 1 end) "PARTIALLY ASSEMBLED",
sum(case when sst.sub_status = 'ASSEMBLED' then 1 end) ASSEMBLED
from tmp t
join sub_status_table sst
on t.wave_num = sst.wave_num
group by t.wave_num, t.int_tasktype
order by t.wave_num
As you notice, I don't know anything about the table with the substatuses.

You can use inner join, grouping and count to get your result:
suppose tables are as follow :
cat (1)--->(n) subcat (1)----->(n) subcat_detail.
so the query would be :
select cat.title cat_title ,subcat.title subcat_title ,count(*) as cnt from
cat inner join sub_cat on cat.id=subcat.cat_id
inner join subcat_detail on subcat.ID=am.subcat_detail_id
group by cat.title,subcat.title

Generally when you need different counts, you need to use the CASE statment.
select count(*) as total
, case when field1 = "test' then 1 else 0 end as testcount
, case when field2 = 'yes' then 1 else 0 endas field2count
FROM table1

Related

How to check unique values in SQL

I have a table named Bank that contains a Bank_Values column. I need a calculated Bank_Value_Unique column to shows whether each Bank_Value exists somewhere else in the table (i.e. whether its count is greater than 1).
I prepared this query, but it does not work. Could anyone help me with this and/or modify this query?
SELECT
CASE
WHEN NULLIF(LTRIM(RTRIM(Bank_Value)), '') =
(SELECT Bank_Value
FROM [Bank]
GROUP BY Bank_Value
HAVING COUNT(*) = 1)
THEN '0' ELSE '1'
END AS Bank_Key_Unique
FROM [Bank]
A windowed count should work:
SELECT
*,
CASE
COUNT(*) OVER (PARTITION BY Bank_Value)
WHEN 1 THEN 1 ELSE 0
END AS Bank_Value_Unique
FROM
Bank
;
It works also, but I found solution also:
select CASE WHEN NULLIF(LTRIM(RTRIM(Bank_Value)),'') =
(select Bank_Value
from Bank
group by Bank_Value
having (count(distinct Bank_Value) > 2 )) THEN '1' ELSE '0' END AS
Bank_Value_Uniquness
from Bank
It was missing "distinct" in having part.

Query - display zero where null in one column and select sum of two columns where not null in next column

I need to display a zero where "Silo Wt" is null, and display the sum of the two values in the Total column even if "Silo Wt" is null.. may not require any changes if I can get a zero in the Silo column
SELECT DISTINCT (coffee_type) AS "Coffee_Type",
(SELECT ItemName
FROM [T01_Item_Name_TBL]
WHERE Item = B.Coffee_Type) AS "Description",
(SELECT COUNT(Green_Inventory_ID)
FROM [Green_Inventory] AS A
WHERE A.Coffee_Type = B.Coffee_Type
AND current_Quantity > 0) AS "Current Units",
SUM((Unit_Weight) * (Current_Quantity)) AS "Green Inv Wt",
(SELECT SUM(TGWeight)
FROM [P04_Green_STotal_TBL] AS C
WHERE TGItem = Coffee_type) AS "Silo Wt",
(SUM((Unit_Weight) * (Current_Quantity)) +
(SELECT SUM(TGWeight)
FROM [P04_Green_STotal_TBL] AS C
WHERE TGItem = Coffee_type)) AS Total
FROM
[Green_Inventory] AS B
WHERE
Pallet_Status = 0
GROUP BY
Coffee_Type
SS of query results now
You just need to wrap them in ISNULL.
However, your query could do with some serious cleanup and simplification:
DISTINCT makes no sense as you are grouping by that column anyway.
Two of the subqueries can be combined using OUTER APPLY, although this requires moving the grouped Green_Inventory into a derived table.
Another subquery, the self-join on Green_Inventory, can be transformed into conditional aggregation.
Not sure whether I've got the logic right, as the subquery did not have a filter on Pallet_Status, but it looks like you would also need to move that condition into conditional aggregation for the SUM, and use a HAVING. It depends exactly on your requirements.
Don't use quoted table or column names unless you have to.
Use meaningful table aliases, rather than A B C.
Specify table names when referencing columns, especially when using subqueries, or you might get unintended results.
SELECT
gi.Coffee_Type,
(SELECT ItemName
FROM T01_Item_Name_TBL AS n
WHERE n.Item = gi.coffee_Type
) AS Description,
ISNULL(gst.TGWeight, 0) AS SiloWt,
ISNULL(gi.GreenInvWt, 0) + ISNULL(gst.TGWeight, 0) AS Total
FROM (
SELECT
gi.Coffee_Type,
COUNT(CASE WHEN gi.current_Quantity > 0 THEN 1 END) AS CurrentUnits,
SUM(CASE WHEN gi.Pallet_Status = 0 THEN gi.Unit_Weight * gi.Current_Quantity END) AS GreenInvWt
FROM
Green_Inventory AS gi
GROUP BY
gi.Coffee_Type
HAVING
SUM(CASE WHEN gi.Pallet_Status = 0 THEN gi.Unit_Weight * gi.Current_Quantity END) > 0
) AS gi
OUTER APPLY (
SELECT SUM(gst.TGWeight) AS TGWeight
FROM P04_Green_STotal_TBL AS gst
WHERE gst.TGItem = gi.Coffee_Type
) AS gst;

Partition table based on joined table

We have 2 Tables Lead and Task.
One lead can have multiple Tasks.
We want to determine if a Lead has a Task who's description contains String 'x'.
If the Lead has the String the it should belong to group1 if it doesn't to group2.
Then we want to count the leads per group and week.
The problem we have is that if a Lead has several tasks and one of them has string 'x' in its description and the others don't it is counted in both groups.
We would need something that resembles a break; statement in the IFF clause of the subquery, so that if the first condition = Contain string x is satisfied the other tasks are not counted anymore.
How would we achieve that?
So far we have the following statement:
--SQL:
SELECT LeadDate, GROUP, COUNT(LEAD_ID_T1)
FROM LEAD Lead INNER JOIN
(SELECT DISTINCT LEAD.ID AS LEAD_ID_T1,
IFF(CONTAINS(Task.DESCRIPTION,
'x'),
'GROUP1',
'GROUP2') AS GROUP
FROM TASK Task
RIGHT JOIN LEAD ON TASK.WHO_ID = LEAD.ID
) T1 ON T1.LEAD_ID_T1 = LEAD.ID
GROUP BY LeadDate,GROUP;
Code breaks because it can not aggregate the measures.
Really thankful for any input. This has been bothering me for a few days now.
I am thinking EXISTS with a CASE expression:
select l.*,
(case when exists (select 1
from task t
where t.who_id = l.id and
t.description like '%x%'
)
then 'GROUP1' else 'GROUP2'
end) as the_group
from lead l;
You can also try something like this, CASE with 1 and 0 then take the SUM
SELECT LeadDate,
sum(CASE When t.description like '%x%'then 1 else 0 end) as Group1,
sum(CASE When t.description like '%x%'then 0 else 1 end) as Group2
FROM TASK t
RIGHT JOIN LEAD l ON t.WHO_ID = l.ID
GROUP BY LeadDate;

Calculate number of rows with having clause

I have 3 tables what I'm trying to achieve is to calculate exact number of rows for two kinds of queries.
The first one must count number of accounts which has exactly only one row in accounts_extra for specific service_id.
The second one must count number of accounts which has exactly only one row in accounts_extra and also trial has not ended for specific id
http://sqlfiddle.com/#!15/313db/3
Basically I get in the first query 0 which is correct but in second query I get 1 which is not correct.
I assume that subscription is optional so that's why I get 1 in the second query what should I do to achieve 0 in the second query but still taken into consideration trial_ends_at
Your question is rather hard to follow, but I think this does what you are describing:
SELECT SUM( (cnt = 1)::int ) as count1,
SUM( (cnt = 1 AND cnt2 > 0)::int ) as count2
FROM (SELECT a.id, COUNT(DISTINCT ae.id) AS cnt,
COUNT(ans.id) as cnt2
FROM accounts a JOIN
accounts_extra ae
ON a.id = ae.account_id LEFT JOIN
account_number_subscriptions ans
ON ans.account_id = a.id AND
ans.trial_ends_at > now()
WHERE a.service_id = '101' AND
a.closed = false AND
ae.created_at < '2019-07-01'
GROUP BY a.id
) a;

Sum distinct records in a table with duplicates in Teradata

I have a table that has some duplicates. I can count the distinct records to get the Total Volume. When I try to Sum when the CompTia Code is B92 and run distinct is still counts the dupes.
Here is the query:
select
a.repair_week_period,
count(distinct a.notif_id) as Total_Volume,
sum(distinct case when a.header_comptia_cd = 'B92' then 1 else 0 end) as B92_Sum
FROM artemis_biz_app.aca_service_event a
where a.Sales_Org_Cd = '8210'
and a.notif_creation_dt >= current_date - 180
group by 1
order by 1
;
Is There a way to only SUM the distinct records for B92?
I also tried inner joining the table on itself by selecting the distinct notification id and joining on that notification id, but still getting wrong sum counts.
Thanks!
Your B92_Sum currently returns either NULL, 1 or 2, this is definitely no sum.
To sum distinct values you need something like
sum(distinct case when a.header_comptia_cd = 'B92' then column_to_sum else 0 end)
If this column_to_sum is actually the notif_id you get a conditional count but not a sum.
Otherwise the distinct might remove too many vales and then you probably need a Derived Table where you remove duplicates before aggregation:
select
repair_week_period,
--no more distinct needed
count(a.notif_id) as Total_Volume,
sum(case when a.header_comptia_cd = 'B92' then column_to_sum else 0 end) as B92_Sum
FROM
(
select repair_week_period,
notif_id
header_comptia_cd,
column_to_sum
from artemis_biz_app.aca_service_event
where a.Sales_Org_Cd = '8210'
and a.notif_creation_dt >= current_date - 180
-- only onw row per notif_id
qualify row_number() over (partition by notif_id order by ???) = 1
) a
group by 1
order by 1
;
#dnoeth It seems the solution to my problem was not to SUM the data, but to count distinct it.
This is how I resolved my problem:
count(distinct case when a.header_comptia_cd = 'B92' then a.notif_id else NULL end) as B92_Sum