Using sub-query to count specific rows - sql

I have a query that I am using for a report. Each line is a row of data containing a medical history, the client_id is repeated for each medical history.
I'm grouping by client_id and summing their conditions but I want to use a sub-query to find any conditions that are above a preset score. My current query is giving me the total for the whole table, not just the specific client_id.
Can someone help me out? Thanks!
Here my query:
select
DATEADD(month, DATEDIFF(month, 0, taken_on), 0),
client_id,
count(hscore),
sum(hscore),
(select count(hscore)
from amexmedscreen
where hscore >= '3.5')
from amexmedscreen
group by taken_on, client_id`

It should be sufficient to use CASE to get 1 for relevant rows, and sum those:
select
...
sum(hscore),
sum(CASE WHEN hscore >= 3.5 THEN 1 ELSE 0 END)
group by taken_on, client_id`

Your subquery is a separate query. It's not constrained by what's going on in the main query. You need to tell it to do the count only for the client_id of the current record in the outer query. You'll be referring to the same table twice in two different queries, so you'll have to use a different alias for each one.
Something like this should work:
select DATEADD(month, DATEDIFF(month, 0, taken_on), 0),
client_id,
count(hscore),
sum(hscore),
(select count(hscore)
from amexmedscreen subq
where
hscore >= '3.5'
and subq.client_id = outerq.client_id )
from amexmedscreen outerq
group by taken_on, client_id

select DATEADD(month, DATEDIFF(month, 0, taken_on), 0),
client_id,
count(hscore),
sum(hscore),
tb1.COUNT_HSCORE
from amexmedscreen
INNER JOIN
(select client_id, count(hscore) as COUNT_HSCORE
from amexmedscreen
where hscore >= '3.5'
group by client_ID) as tb1
ON tb1.client_id = client id
group by taken_on, client_id,tb1.COUNT_HSCORE

Related

Two Table Join Into One Result

I have two tables where I am attempting to join the results into one. I am trying to get the INV_QPC which is the case pack size shown in the results (SEIITN and SKU) are the same product numbers.
The code below gives two results, but the goal is to get the bottom result into the main output, where I was hoping the join would be the lookup to show the case pack size in relation to SKU.
INV_QPC = case pack size
SKU = SKU/Product Number
SEIITN = SKU/Product Number
Thanks for looking.
SELECT
ORDER_QTY, SKU, INVOICE_NUMBER, CUSTOMER_NUMBER, ROUTE,
ALLOCATED_QTY, SHORTED_QTY, PRODUCTION_DATE,
DATEPART(wk, PRODUCTION_DATE) AS FISCAL_WEEK,
YEAR(PRODUCTION_DATE) AS FISCAL_YEAR,
CONCAT(SKU, CUSTOMER_NUMBER) AS SKU_STORE_WEEK
FROM
[database].[dbo].[ORDERS]
WHERE
[PRODUCTION_DATE] >= DATEADD(day, -3, GETDATE())
AND [PRODUCTION_DATE] <= GETDATE()
SELECT INV_QPC
FROM [database].[dbo].[PRODUCT_MASTER]
JOIN [database].[dbo].[ORDERS] ON ORDERS.SKU = PRODUCT_MASTER.SEIITN;
It looks like you are on the right track, but your second SQL statement is only returning the INV_QPC column, so it is not being joined to the first query. Here is an updated SQL statement that should give you the result you are looking for:
SELECT
ORD.ORDER_QTY, ORD.SKU, ORD.INVOICE_NUMBER, ORD.CUSTOMER_NUMBER, ORD.ROUTE,
ORD.ALLOCATED_QTY, ORD.SHORTED_QTY, ORD.PRODUCTION_DATE,
DATEPART(wk, ORD.PRODUCTION_DATE) AS FISCAL_WEEK,
YEAR(ORD.PRODUCTION_DATE) AS FISCAL_YEAR,
CONCAT(ORD.SKU, ORD.CUSTOMER_NUMBER) AS SKU_STORE_WEEK,
PROD.INV_QPC
FROM
[database].[dbo].[ORDERS] ORD
JOIN [database].[dbo].[PRODUCT_MASTER] PROD ON ORD.SKU = PROD.SEIITN
WHERE
ORD.PRODUCTION_DATE >= DATEADD(day, -3, GETDATE())
AND ORD.PRODUCTION_DATE <= GETDATE()
In this query, I have added the INV_QPC column to the SELECT statement, and also included the join condition in the JOIN clause. Additionally, I have given aliases to the tables in the FROM and JOIN clauses to make the query easier to read. Finally, I have updated the WHERE clause to reference the ORD alias instead of the table name directly.

How to filter Users that meet CASE criteria without nesting WHERE in SQL?

Right now I have a query that lets me know which users didn't make a purchase 12 months prior to becoming members. These users have MEM_PRE_12=0 and I want to filter off those users more natively using SQL partitions rather than always putting rudimentary WHERE criteria.
Here is the SQL I use to find the users I want/don't want.
SELECT SUM(CASE WHEN DATE <= DATEADD(month, -12, U.INSERTED_AT) THEN 1 ELSE 0 END) AS MEM_PRE_12, I.CLIENTID, I.INSTALLATIONID
FROM <<<My_Joined_Tables>>>
GROUP BY I.CLIENTID, I.INSTALLATIONID
HAVING MEM_PRE_12 != 0
ORDER BY MEM_PRE_12
After this I'm going to have to go back and say where I.CLIENTID in the above nested query and select the actual information I want from users who made purchases greater than their insertion date.
How can I do this without so much nesting of all these joined tables?
If you want the detailed rows for customers who made a purchase in the last 12 months, you can use window functions:
with q as (
<whatever your query logic is>
)
select q.*
from (select q.*,
SUM(CASE WHEN DATE <= DATEADD(month, -12, U.INSERTED_AT) THEN 1 ELSE 0 END) over (partition by CLIENTID, INSTALLATIONID) as AS MEM_PRE_12
from q
) q
where mem_pre_12 > 0;

SQL with as expression shows multiple results

I am writing a SQL query using with as expression. I always get a result in the square of what I required.
This is my query:
DECLARE #MAX_DATE AS INT
SET #MAX_DATE = (SELECT DATEPART(MONTH,FECHA) FROM ALBVENTACAB WHERE NUMALBARAN IN (SELECT DISTINCT MAX(NUMALBARAN) FROM ALBVENTACAB));
;WITH TABLE_LAST AS (
SELECT CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA)) as LAST_YEAR_MONTH
,SUM(TOTALNETO) AS LAST_YEAR_VALUE
FROM ALBVENTACAB
WHERE DATEPART(YEAR,CURRENT_TIMESTAMP) -1 = DATEPART(YEAR,FECHA) AND NUMSERIE LIKE 'A%'
AND DATEPART(MONTH,FECHA) <= #MAX_DATE
GROUP BY CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA))
)
,TABLE_CURRENT AS(
SELECT CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA)) as CURR_YEAR_MONTH
,SUM(TOTALNETO) AS CURR_YEAR_VALUE
FROM ALBVENTACAB
WHERE DATEPART(YEAR,CURRENT_TIMESTAMP) <= DATEPART(YEAR,FECHA) AND NUMSERIE LIKE 'A%'
GROUP BY CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA))
)
SELECT *
FROM TABLE_CURRENT, TABLE_LAST
When I run the query I get exactly the square of the result.
I want to compare sale monthly with last year.
2-2020 814053.3 2-2019 840295.1
1-2020 1094993.65 2-2019 840295.1
3-2020 293927.3 2-2019 840295.1
2-2020 814053.3 1-2019 1050701.68
1-2020 1094993.65 1-2019 1050701.68
3-2020 293927.3 1-2019 1050701.68
2-2020 814053.3 3-2019 887776.1
1-2020 1094993.65 3-2019 887776.1
3-2020 293927.3 3-2019 887776.1
I should get only 3 rows instead of 9 rows.
You need to properly join your two CTE - the way you're doing it now, you're getting a Cartesian product of each row in either CTE together.
Do something like:
*;WITH TABLE_LAST AS
( ....
),
TABLE_CURRENT AS
( ....
)
SELECT *
FROM TABLE_CURRENT curr
INNER JOIN TABLE_LAST last ON (some join condition here)
What that join condition is going to be - I have no idea, and cannot tell from your question - but you have to define how these two sets of data "connect" ....
It could be something like:
SELECT *
FROM TABLE_CURRENT curr
INNER JOIN TABLE_LAST last ON curr.CURR_YEAR_MONTH = last.LAST_YEAR_MONT
or whatever else makes sense in your situation - but basically, you need to somehow "tie together" these two sets of data and get only those rows that make sense - not just every row from "last" combined with every row from "curr" ....
While you already got the answer on how to join the two results, I thought I'd tell you how to typically approach such problems.
From the same table, you want two sums on different conditions (different years that is). You solve this with conditional aggregation, which does just that: aggregate (sum) based on a condition (year).
select
datepart(month, fecha) as month,
sum(case when datepart(year, fecha) = datepart(year, getdate()) then totalneto end) as this_year,
sum(case when datepart(year, fecha) = datepart(year, getdate()) -1 then totalneto end) as last_year
from albventacab
where numserie like 'A%'
and fecha > dateadd(year, -2, getdate())
group by datepart(month, fecha)
order by datepart(month, fecha);

joining three select statements

I create reports in SQL Server Report Builder. I hope anyone can help me in this case. My query shows me an error if I add a third inner join
How can I add a third select statement?
You need to update the final GROUP BY clause. Including the full name in the SELECT clause requires the full name in the GROUP BY.
As a rule of thumb: When using GROUP BY every field used in the SELECT clause, that isn't combined with an aggregate function, must appear.
Select
SUM(cast(Units as int)) as CounterName,
left(Name,4) as Machine,
Name as WasteLabel
from
Trouble
inner join tsystem ON Trouble.systemid = tsystem.id
where
Name not in ('Aus', 'An', 'Produced')
and IntervalDateWeek >= dateadd(wk, datediff(wk, 0, getdate()) - 2, 0)
and IntervalDateWeek <= dateadd(wk, datediff(wk, 0, getdate())-1, 0)
and left(Name, 4) in (Select name from tSystem
where
ID in
(
Select
systemid
from
tsystemviewSystemwhere
WHERE
SystemViewID = 4)
)
group by
Name
I suspect your query could be improved. Adding clear sample data and expected output will help here.

Access database query for using month from a date

I have the following table schema in acess (2007).
Date eventDate bit(boolean) lunch,
bit(boolean) snacks, bit(boolean) Tea,
I would like to have a single query that gives count of luch, snacks and tea (each as a column) for a given month (using the eventdate).
Thanks for help.
In Access, True is -1 and False is 0. So you can use the absolute value of the sum of those values to indicate how many were True.
SELECT Abs(Sum(lunch)) AS SumofLunch, Abs(Sum(snacks)) AS SumofSnacks, Abs(Sum(Tea)) AS SumofTea
FROM YourTable
WHERE eventDate >= #2009/08/01# And eventDate < #2009/09/01#;
Try:
SELECT SUM(ABS(lunch)) AS lunchCount, SUM(ABS(snacks)) AS snackCount, SUM(ABS(tea)) AS teaCount
FROM <TableName>
WHERE eventDate >= #1/1/2009# AND eventDate < #2/1/2009#
I'd attack this in access using IIF statements (think like CASE statements in other databases). IIF in Access returns a value when the specified condition is true (after the first comma) or another value if it evaluates to false (after the second comma). Because you are using booleans, checking for a true condition and rolling up via an aggregate sum will do the trick for you.
SELECT Month(EventDate) AS TheMonth, Year(EventDate) AS TheYear,
SUM(IIF(Lunch, 1, 0)) AS LunchCount,
SUM(IIF(Snacks, 1, 0)) AS SnackCount,
SUM(IIF(Tea, 1, 0)) AS TeaCount
FROM YourTable
GROUP BY Month(EventDate), Year(EventDate)
ORDER BY Month(EventDate), Year(EventDate)
The above query of course returns counts for all months and years however you could easily key in on a date range like below if need be.
SELECT Month(EventDate) AS TheMonth, Year(EventDate) AS TheYear,
SUM(IIF(Lunch, 1, 0)) AS LunchCount,
SUM(IIF(Snacks, 1, 0)) AS SnackCount,
SUM(IIF(Tea, 1, 0)) AS TeaCount
FROM YourTable
WHERE EventDate BETWEEN #1/1/2009# AND #1/31/2009#
GROUP BY Month(EventDate), Year(EventDate)
ORDER BY Month(EventDate), Year(EventDate)