SQL Query to find total count in certain price range - sql

Need your help with a SQL Query and how should I write it?
I have a table with total_value and order_id and would like to find the number of orders whose total value is in the range of 0-50, 51-100, over 100
Thank you !

you want a case statement.
something like:
select count(order_id),
value_range
from
(select order_id,
total_value,
case when total_value between 0 and 50 then '0-50'
when total_value between 51 and 100 then '51-100'
when total_value > 100 then '100'
end as value_range
from table)a
group by value_range

Perhaps this will work for you:
select count(order_id),
valueRange
from
(select order_id,
total_value,
case when total_value between 0 and 50 then '0-50'
when total_value between 51 and 100 then '51-100'
when total_value > 100 then '100'
end as valueRange
from table)a
Group by valueRange

Using Conditional SUM:
SELECT SUM(CASE WHEN Total_Value BETWEEN 0 AND 50 THEN 1 ELSE 0 END) As Range1
, SUM(CASE WHEN Total_Value BETWEEN 51 AND 100 THEN 1 ELSE 0 END) As Range2
, SUM(CASE WHEN Total_Value > 100 THEN 1 ELSE 0 END) As Range3
FROM your_table

Related

Get users that have at least one product code and also more than 10 of the other product code

The table that needs to be queried looks like this:
ID
UserID
ProductCodes
1
33
9999
2
456
3051
3
456
9999
4
456
3051
4
33
9999
How would I write a SQL query to find out which users have at least one productCodes = '9999' and also have more than 10 productCodes <> '9999'?
You can use GROUP BY and HAVING:
SELECT
UserID
FROM dbo.YourTable
GROUP BY
UserId
HAVING SUM(CASE WHEN ProductCodes = '9999' THEN 1 ELSE 0 END) >= 1
AND COUNT(DISTINCT ProductCodes) >= 11
;
Use Case or Intersect (case is more performant)
SELECT UserID, SUM (case when ProductCodes='9999' then 1 else 0 end) PC9999
, SUM (case when ProductCodes<>'9999' then 1 else 0 end) PCNot9999
FROM dbo.Users
WHERE ProductCodes='9999'
GROUP BY UserID
HAVING SUM (case when ProductCodes='9999' then 1 else 0 end)>0
AND SUM (case when ProductCodes<>'9999' then 1 else 0 end) >10
I ended up going with this. It allows us to get specific with how many times a '9999' product code has been used in comparison with other codes.
SELECT
UserID
FROM Session_Hst
GROUP BY
UserID
HAVING SUM(CASE WHEN ProductCodes = '9999' THEN 1 ELSE 0 END) >= 1
AND COUNT(CASE WHEN ProductCodes <> '9999' THEN 1 ELSE null END ) >= 10
;

One select statement with multiple Group BY on the same column

I have 'TABLE_A' like this:
TVA Amount InvoiceID
----------------------
22 | 10.00 | inv-12
22 |-14.00 | inv-13
25 | 24.00 | inv-14
25 |-36.00 | inv-15
25 |-25.00 | inv-16
25 | 18.50 | inv-17
24 |-16.50 | inv-18
24 | 10.00 | inv-19
The goal is to make a groupBy TABLE_A.TVA value and by SUM(TABLE_A.Amount) > 0 and SUM(TABLE_A.Amount) <0, to get finally the sum of all positive Amounts grouped by TVA value, and the sum of all negative amounts grouped by their TVA value also
my Query is like this:
SELECT TABLE_A.TVA, TABLE_A.InvoiceID,
SUM(TABLE_A.Amount) AS [PositiveTotalAMount],
SUM(TABLE_A.Amount) AS [NegativeTotalAMount]
FROM TABLE_A
GROUP BY TABLE_A.TVA
HAVING SUM(TABLE_A.TVA) > 0
MY question is how to add the second grouping by on negative values, because here i group only on SUM() > 0
You can use a CASE (Transact-SQL) expression:
SELECT
A.TVA,
A.InvoiceID,
SUM(CASE WHEN A.Amount > 0 THEN A.Amount ELSE 0 END) AS [PositiveTotalAMount],
SUM(CASE WHEN A.Amount < 0 THEN A.Amount ELSE 0 END) AS [NegativeTotalAMount]
FROM
TABLE_A A
GROUP BY
A.TVA,
A.InvoiceID
Also, you must include all columns from the select list that are not aggregated to the GROUP BY list. InvoiceID was missing.
I also use the alias A for TABLE_A to increase readability.
With conditional aggregation:
SELECT
TABLE_A.TVA,
SUM(CASE WHEN TABLE_A.Amount > 0 THEN TABLE_A.Amount ELSE 0 END) AS [PositiveTotalAMount],
SUM(CASE WHEN TABLE_A.Amount < 0 THEN TABLE_A.Amount ELSE 0 END) AS [NegativeTotalAMount]
FROM TABLE_A
GROUP BY TABLE_A.TVA
If you want to include the column TABLE_A.InvoiceID in the grouping then:
SELECT
TABLE_A.TVA,
TABLE_A.InvoiceID,
SUM(CASE WHEN TABLE_A.Amount > 0 THEN TABLE_A.Amount ELSE 0 END) AS [PositiveTotalAMount],
SUM(CASE WHEN TABLE_A.Amount < 0 THEN TABLE_A.Amount ELSE 0 END) AS [NegativeTotalAMount]
FROM TABLE_A
GROUP BY TABLE_A.TVA, TABLE_A.InvoiceID

Transpose SQL row headers to first column

What is the shortest, fastest, easiest way to transpose the results of the query below? I want the 0-3 and 3-6 to show in the first column. Sorry but this is one of those things that will boggle me for days if I don't reach out. Thanks in advance.
SELECT SUM (CASE WHEN CMAPR BETWEEN 0 AND 3 THEN 1 ELSE 0 END) AS [0-3],
SUM (CASE WHEN CMAPR BETWEEN 3.01 AND 6 THEN 1 ELSE 0 END) AS [3-6]
FROM TBL
Current Results:
Use aggregation:
SELECT (CASE WHEN CMAPR >= 0 AND CMAPR <=3 THEN '0-3'
WHEN CMAPR <= 6 THEN '3-6'
ELSE 'Other'
END) AS grp, COUNT(*)
FROM tbl
GROUP BY (CASE WHEN CMAPR >= 0 AND CMAPR <=3 THEN '0-3'
WHEN CMAPR <= 6 THEN '3-6'
ELSE 'Other'
END);
The only downside is that this will not return a group if it has no rows.
You can simply unpivot your query by doing:
SELECT v.*
FROM (SELECT SUM (CASE WHEN CMAPR BETWEEN 0 AND 3 THEN 1 ELSE 0 END) AS [0-3],
SUM (CASE WHEN CMAPR BETWEEN 3.01 AND 6 THEN 1 ELSE 0 END) AS [3-6]
FROM TBL
) x CROSS APPLY
(VALUES ('[0-3]', [0-3]), ('[3-6]', [3-6])) v(which, val);

Use of AVG function to determine percentages in a SQL query

I want to know what percentage of records have a given value, where percentage is defined as the number of records that match the value divided by the total number of records. i.e. if there are 100 records, of which 10 have a null value for student_id and 20 have a value of 999999, then the percentage_999999 should be 20%. Can I use the AVG function to determine this?
Option 1:
SELECT year, college_name,
sum(case when student_id IN ('999999999') then 1 else 0 end) as count_id_999999999,
count_id_999999999/total_id as percent_id_999999999,
sum(case when student_id IS NULL then 1 else 0 end) as count_id_NULL,
count_id_NULL/total_id as percent_id_NULL
count(*) as total_id
FROM enrolment_data ed
GROUP BY year, college_name
ORDER BY year, college_name;
Option 2:
SELECT year, college_name,
sum(case when student_id IN ('999999999') then 1 else 0 end) as count_id_999999999,
avg(case when student_id IN ('999999999') then 1.0 else 0 end) as percent_id_999999999,
sum(case when student_id IS NULL then 1 else 0 end) as count_id_NULL,
avg(case when student_id IS NULL then 1.0 else 0 end) as percent_id_NULL
count(*) as total_id
FROM enrolment_data ed
GROUP BY year, college_name
ORDER BY year, college_name;
I created a similar table with 100 records, 20 999999999s, 10 nulls, and 70 1s. This worked for me on SQL Server:
select count(*), StudentID
from ScratchTbl
group by StudentID;
(No column name) StudentID
10 NULL
70 1
20 999999999
select avg(case when StudentID = '999999999' then 1.0 else 0.0 end) as 'pct_9s',
sum(case when StudentID = '999999999' then 1 else 0 end) as 'count_9s',
avg(case when StudentID is null then 1.0 else 0.0 end) as 'pct_null',
sum(case when StudentID is null then 1 else 0 end) as 'count_null'
from ScratchTbl
pct_9s count_9s pct_null count_null
0.200000 20 0.100000 10
I have a feeling that your use of the group by clause could be creating problems for you, perhaps select a specific year/college using the where clause (and get rid of the group by line) and see if you get the results you expect.

sql subquery that collects from 3 rows

I have a huge database with over 4 million rows that look like that:
Customer ID Shop
1 Asda
1 Sainsbury
1 Tesco
2 TEsco
2 Tesco
I need to count customers that within last 4 weeks had shopped in all 3 shops Tesco Sainsbury and Asda. Can you please advice if its possible to do it with subqueries?
This is an example of a "set-within-sets" subquery. You can solve it with aggregation:
select customer_id
from Yourtable t
where <shopping date within last four weeks>
group by customer_id
having sum(case when shop = 'Asda' then 1 else 0 end) > 0 and
sum(case when shop = 'Sainsbury' then 1 else 0 end) > 0 and
sum(case when shop = 'Tesco' then 1 else 0 end) > 0;
This structure is quite flexible. So if you wanted Asda and Tesco but not Sainsbury, then you would do:
select customer_id
from Yourtable t
where <shopping date within last four weeks>
group by customer_id
having sum(case when shop = 'Asda' then 1 else 0 end) > 0 and
sum(case when shop = 'Sainsbury' then 1 else 0 end) = 0 and
sum(case when shop = 'Tesco' then 1 else 0 end) > 0;
EDIT:
If you want a count, then use this as a subquery and count the results:
select count(*)
from (select customer_id
from Yourtable t
where <shopping date within last four weeks>
group by customer_id
having sum(case when shop = 'Asda' then 1 else 0 end) > 0 and
sum(case when shop = 'Sainsbury' then 1 else 0 end) > 0 and
sum(case when shop = 'Tesco' then 1 else 0 end) > 0
) t