SQL show entries where a specific field shows up multiple times - sql

First off here is the data that I am currently using:
Name, Phone, Email & InvoiceCost
I am trying to write a query that selects the Name, Phone & Email details where
The user (identified by email) has made 2 or more purchases within the last 180 days
The total cost of all of the invoices within these 180 days comes up to over 500
Below is the SQL that I have come up with so far but I doubt that will be of any use at all:
SELECT Name, Phone, Email, InvoiceCost
FROM INVOICE JOIN
(SELECT INVOICE.Email, count(*) AS TotalCount,
SUM(
CASE WHEN INVOICE.InvoiceDate >= (GETDATE() - 180)
THEN 1
ELSE 0
END) AS LastSixMonths
FROM INVOICE
GROUP BY INVOICE.Email) e
ON INVOICE.Email = e.Email
WHERE (e.TotalCount > 1 AND e.LastSixMonths = 1);
I can't figure out how to incorporate the total cost part, please help!

Assuming you would consider unique combinations of Name, Phone, and Email as individual customers:
SELECT Name, Phone, Email, Count(*) AS TotalCount, Sum(InvoiceCost) AS TotalCost
FROM INVOICE
GROUP BY Email, Name, Phone
WHERE DateDiff(d, InvoiceDate, GETDATE()) <= 180
HAVING Count(*) >= 2 OR Sum(InvoiceCost) > 500.0

Related

How to count certain the ages of people who have a log record from another table in sql?

I want to get a count of how many people who are 18 are recorded in the logs table only once. Now if I have the same person who entered 2 times, I can see that there are 2 people with age 18. I can't make it appear only once. How do I do this???
My logs table and people table are connected by card_id.
My logs table has the login date and card_id.
While my members' table has the birthdate and card_id columns.
HERE is the query I made
select
card_id, sum("18") as "18"
from
( select logs.login, members.card_id,
count(distinct (case when 0 <= age and age <= 18 then age end)) as "18",
count( (case when 19 <= age and age <= 30 then age end)) as "30",
count ( (case when 31 <= age and age <= 50 then age end)) as "50"
from
(select login, date_part('year', age(birthdate)) as age, members.card_id as card_id,
logs.login
from members
left join logs on logs.card_id=members.card_id
) as members
left join logs on logs.card_id=members.card_id
group by logs.login, members.card_id
) as members
where login <= '20221029' group by card_id;
I want to create a table like this:
18 | 30 | 50 |
---------------
2 | 0 | 0
Count the distinct card_id-s.
select count(distinct card_id)
from members join logs using (card_id)
where extract('year' from age(birthdate)) = 18
and login <= '20221029';
Unrelated but it seems that you are storing login as text. This is not a good idea. Use type date instead.
Addition afer the question update
select count(*) filter (where user_age = 18) as age_18,
count(*) filter (where user_age between 19 and 30) as age_30,
count(*) filter (where user_age between 31 and 50) as age_50
from
(
select distinct on (card_id)
extract('year' from age(birthdate)) user_age
from members inner join logs using (card_id)
where login <= '20221029'
order by card_id, login desc -- pick the latest login
) AS t;

How to get the asked columns for each customers

I have this table called table a
I need to get the CustomerID, sum(Income) of 2015, sum(Income) of 2016, did he ever bought productId A (boolean), is the total sum(income)> 1000 (boolean), number of total InvoiceID
all that in one query and the results should be with 1 row per customer.
please help I don't even know how to start!
This is basically conditional aggregation:
select customerid,
sum(case when extract(year from date) = 2015 then sales end) as sales_2015,
sum(case when extract(year from date) = 2016 then sales end) as sales_2016,
max( product = 'A' ) as ever_bought_a,
sum(income) > 1000 as sum_exceeds_1000,
count(*) as num_invoices
from t
group by customerid;
You haven't specified a database, so this is really psuedocode. You'll need to adapt it for your particular database.

Combine and fuse the results of two SQL queries with UNION

I am writing two seperate SQL queries to get data for two different dates like so:
SELECT number, sum(sales) as sales, sum(discount) sa discount, sum(margin) as margin
FROM table_a
WHERE day = '2019-08-09'
GROUP BY number
SELECT number, sum(sales) as sales, sum(discount) sa discount, sum(margin) as margin
FROM table_a
WHERE day = '2018-08-10'
GROUP BY number
I tried fusing them like so to get the results for the same number in one row from two different dates:
SELECT number, sum(sales) as sales, sum(discount) sa discount, sum(margin) as margin, 0 as sales_n1, 0 as discount_n1, 0 as margin_n1
FROM table_a
WHERE day = '2019-08-09'
GROUP BY number
UNION
SELECT number, 0 as sales, 0 as discount, 0 as margin, sum(sales_n1) as sales_n1, sum(discount_n1) as discount_n1, sum(margin_n1) as margin_n1
FROM table_a
WHERE day = '2018-08-10'
GROUP BY number
But it didn't work as I get the rows for the first query with zeroes for the columns defined as zero followed by the columns of the second query in the same fashion.
How can I correct this to have the desired output ?
Use conditional aggregation:
SELECT number,
sum(case when day = '2019-08-09' then sales end) as sales_20190809,
sum(case when day = '2019-08-09' then discount end) sa discount, sum(margin) as margin_20190810,
sum(case when day = '2019-08-10' then sales end) as sales_20190809,
sum(case when day = '2019-08-10' then discount end) sa discount, sum(margin) as margin_20190810
FROM table_a
WHERE day IN ('2019-08-09', '2019-08-10')
GROUP BY number;
If you want the numbers in different rows (which you don't seem to), then use aggregation:
SELECT day, number, sum(sales) as sales, sum(discount) as discount, sum(margin) as margin
FROM table_a
WHERE day IN ('2019-08-09', '2019-08-10')
GROUP BY day, number

Group by the Sub-Query which is derived from WITH CLAUSE [duplicate]

This question already has answers here:
ORA-00979 not a group by expression
(10 answers)
Closed 7 years ago.
I'm getting error for my below query, while I'm trying to grouping the sub-query. I built the sub-query using the WITH Clause.
Please correct me
WITH Student AS (SELECT * FROM CLASS WHERE SEX='M')
SELECT NAME, AGE, STATUS, SUM(TOTAL)
(SELECT
NAME,
'15' AS AGE,
CASE WHEN ATTENDANCE > 50 AND ATTENDANCE < 60 THEN 'GOOD'
WHEN ATTENDANCE > 60 'GREAT'
ELSE 'BAD' END AS STATUS
SUM (MARK) AS TOTAL
FROM STUDENT
GROUP BY NAME, ATTENDANCE ) A
GROUP BY NAME, AGE, STATUS
Error: SQL Query not properly ended
I think you are missing a from clause:
WITH Student AS (SELECT * FROM CLASS WHERE SEX='M')
SELECT NAME, AGE, STATUS, SUM(TOTAL)
FROM (SELECT NAME, '15' AS AGE,
(CASE WHEN ATTENDANCE > 50 AND ATTENDANCE < 60 THEN 'GOOD'
WHEN ATTENDANCE > 60 'GREAT'
ELSE 'BAD'
END) AS STATUS,
SUM(MARK) AS TOTAL
FROM STUDENT
GROUP BY NAME, ATTENDANCE
) A
GROUP BY NAME, AGE, STATUS
The query is much longer than it needs to be to achieve the output you want, but this seems to be the problem you have.

Grouping multiple selects within a SQL query

I have a table Supplier with two columns, TotalStock and Date. I'm trying to write a single query that will give me stock totals by week / month / year for a list of suppliers.
So results will look like this..
SUPPLIER WEEK MONTH YEAR
SupplierA 50 100 2000
SupplierB 60 150 2500
SupplierC 15 25 200
So far I've been playing around with multiple selects but I can't get any further than this:
SELECT Supplier,
(
SELECT Sum(TotalStock)
FROM StockBreakdown
WHERE Date >= '2014-5-12'
GROUP BY Supplier
) AS StockThisWeek,
(
SELECT Sum(TotalStock)
FROM StockBreakdown
WHERE Date >= '2014-5-1'
GROUP BY Supplier
) AS StockThisMonth,
(
SELECT Sum(TotalStock)
FROM StockBreakdown
WHERE Date >= '2014-1-1'
GROUP BY Supplier
) AS StockThisYear
This query throws an error as each individual grouping returns multiple results. I feel that I'm close to the solution but can't work out where to go
You don't have to use subqueries to achieve what you want :
SELECT Supplier
, SUM(CASE WHEN Date >= CAST('2014-05-12' as DATE) THEN TotalStock END) AS StockThisWeek
, SUM(CASE WHEN Date >= CAST('2014-05-01' as DATE) THEN TotalStock END) AS StockThisMonth
, SUM(CASE WHEN Date >= CAST('2014-01-01' as DATE) THEN TotalStock END) AS StockThisYear
FROM StockBreakdown
GROUP BY Supplier
You may need to make the selects for the columns return only a single result. You could try this (not tested currently):
SELECT Supplier,
(
SELECT TOP 1 StockThisWeek FROM
(
SELECT Supplier, Sum(TotalStock) AS StockThisWeek
FROM StockBreakdown
WHERE Date >= '2014-5-12'
GROUP BY Supplier
) tmp1
WHERE tmp1.Supplier = Supplier
) AS StockThisWeek,
(
SELECT TOP 1 StockThisMonth FROM
(
SELECT Supplier, Sum(TotalStock) AS StockThisMonth
FROM StockBreakdown
WHERE Date >= '2014-5-1'
GROUP BY Supplier
) tmp2
WHERE tmp2.Supplier = Supplier
) AS StockThisMonth,
...
This selects the supplier and then tries to create two columns StockThisWeek and StockThisMonth by selecting the first entry from the select you created before. As through the GROUP BY there should only be one entry per supplier, so you don't lose and data.