My sql looks like:
create table ad(
ad_id int,
ad_name varchar(10)
);
insert into ad(ad_id, ad_name) values
(1,'ad1'),
(2,'ad2'),
(3,'ad3');
create table ad_insight(
id int,
ad_id int,
date date,
clicks int
);
insert into ad_insight(id, ad_id, date, clicks) values
(1, 1, '2021-04-25', 1),
(2, 1, '2021-04-24', 4),
(3, 1, '2021-04-23', 2),
(4, 2, '2021-04-25', 6),
(5, 2, '2021-03-03', 7);
create table product(
product_id int,
ad_id int,
product_name varchar(10)
);
insert into product(product_id, ad_id, product_name) values
(1, 1, 'prod1'),
(2, 1, 'prod2'),
(3, 2, 'prod3'),
(4, 2, 'prod4');
(1, 3, 'prod1');
create table product_insight(
id int,
product_id int,
sale int,
date date
);
insert into product_insight(id, product_id, sale, date) values
(1, 1, 12, '2021-04-25'),
(2, 1, 11, '2021-04-24'),
(3, 1, 13, '2021-04-23'),
(4, 1, 14, '2021-04-22'),
(5, 1, 17, '2021-04-21'),
(6, 1, 15, '2021-04-20'),
(7, 1, 13, '2021-04-19'),
(8, 2, 19, '2021-04-25');
Here you have fiddle
A quick explanation of schema:
I have ads:
each ad has insights, which tell us when a certain ad was active.
each ad has products. Each product has product_insight which tells us how many sales that product generated on a certain day.
And now I want to get the following tables:
which will sum up clicks from ad_insight table and sum up product_sale from product_insight in 2021-04-23 to 2021-04-25 inclusive.
+----------+--------+--------------+--------------+
| ad_name | clicks | product_sale | products |
+----------+--------+--------------+--------------+
| ad1 | 7 | 55 | prod1, prod2 |
| ad2 | 6 | 0 | prod3, prod4 |
| ad3 | 0 | 36 | prod1 |
+----------+--------+--------------+--------------+
The summary row which will sum up everything in the above table:
+------------+--------------+--------------------+----------------------------+
| total_ads | total_clicks | total_product_sale | unique_all_products |
+------------+--------------+--------------------+----------------------------+
| 3 | 13| 91 | prod1, prod2, prod3, prod4 |
+------------+--------------+--------------------+----------------------------+
What I have tried?
# 1) table
select ad_name, SUM(ad_insight.clicks) as clicks
from ad
left join ad_insight on ad.ad_id = ad_insight.ad_id
where ad_insight.date >= '2021-04-23' and ad_insight.date <= '2021-04-25'
group by ad.ad_id;
# 2) table
select count(distinct ad_insight.ad_id) as total, SUM(ad_insight.clicks) as clicks
from ad_insight
left join ad on ad.ad_id = ad_insight.ad_id
where ad_insight.date >= '2021-04-23' and ad_insight.date <= '2021-04-25'
But I do not know how select product_sale table and products separated by comma!
If I understand correctly, you want to aggregate along two different dimensions (clicks and sales) for each ad. Aggregate before joining:
select ad.ad_name, ai.clicks, p.sales, p.products
from ad left join
(select ai.ad_id, sum(ai.clicks) as clicks
from ad_insight ai
where ai.date >= '2021-04-23' and ai.date <= '2021-04-25'
group by ai.ad_id
) ai
on ad.ad_id = ai.ad_id left join
(select p.ad_id, sum(pi.sale) as sales,
group_concat(distinct p.product_name) as products
from product p join
product_insight pi
on pi.product_id = p.product_id
where pi.date >= '2021-04-23' and pi.date <= '2021-04-25'
group by p.ad_id
) p
on p.ad_id = ad.ad_id ;
The second query just aggregates this again.
Related
How can I find the restaurant name and the total number of orders for each in Jan 2021? The issue I'm facing is that the restaurant names and the orders are on separate tables as you can see from the code below.
create table orders (id integer, country text, customer_id integer,
restaurant_id INTEGER, date date, order_value integer);
create table customers (id integer, name text, country text);
create table restaurants (id integer, name text, country text);
INSERT INTO orders (
id,
country,
customer_id,
restaurant_id,
date,
order_value)
VALUES
(1, 'Pakistan', 1, 1, '2021-01-01', 400),
(2, 'Pakistan', 2, 1, '2021-01-01', 500),
(3, 'Pakistan', 4, 2, '2021-01-01', 300),
(4, 'Pakistan', 4, 3, '2021-01-05', 200),
(5, 'Pakistan', 5, 4, '2021-01-01', 250),
(6, 'Pakistan', 4, 1, '2021-01-09', 266),
(7, 'Pakistan', 3, 2, '2021-01-07', 322),
(1, 'Holland', 1, 1, '2021-01-01', 378),
(8, 'Pakistan', 1, 3, '2021-06-01', 289),
(2, 'Holland', 1, 1, '2021-08-01', 480),
(9, 'Pakistan', 1, 1, '2021-03-01', 580),
(10, 'Pakistan', 3, 2, '2021-07-01', 360),
(3, 'Holland', 1, 1, '2021-09-01', 550),
(11, 'Pakistan', 4, 3, '2021-04-01', 991),
(12, 'Pakistan', 5, 1, '2021-04-01', 875),
(4, 'Holland', 1, 1, '2021-03-02', 250),
(13, 'Pakistan', 1, 1, '2021-08-01', 150),
(14, 'Pakistan', 1, 2, '2021-09-01', 290),
(5, 'Holland', 1, 1, '2021-07-01', 240),
(15, 'Pakistan', 1, 3, '2021-03-01', 780),
(16, 'Pakistan', 1, 4, '2021-06-01', 987),
(6, 'Holland', 1, 1, '2021-05-03', 457),
(17, 'Pakistan', 1, 4, '2021-05-04', 258);
INSERT INTO customers (
id,
name,
country)
VALUES
(1, 'Steven Smith', 'Pakistan'),
(2, 'Arthur Chen', 'Holland'),
(3, 'Michael Wren', 'Pakistan'),
(4, 'John Almagro', 'Pakistan'),
(5, 'Luke Pablo', 'Pakistan'),
(6, 'Monty Tron', 'Pakistan');
INSERT INTO restaurants (
id,
name,
country)
VALUES
(1, 'KFC', 'Pakistan'),
(2, "McDonald's", 'Holland'),
(3, 'Howdy', 'Pakistan'),
(4, 'Kitchen Cuisine', 'Pakistan'),
(5, 'JFC', 'Pakistan'),
(6,'Hardees','Pakistan');
I learned about JOIN functions but I'm not able to join the dots.
Joining two table, is made by telling the database, which rows belong together. this is defined in the ON clause, where the joning columns are mentioned.
the WHERE clause is the same as in the last query it removes all rows that have not the right year and month.
The Group By has here three columns, because the restaurant_id has always the same value. We could also had added a aggregation function to the columns, which would have the same effect
SELECT
r.name,
r.country,
COUNT(*) Total_orders
FROM
orders o JOIN restaurants r ON o.restaurant_id = r.id
WHERE YEAR(`date`)= 2021 AND MONTH(`date`)= 1
GROUP BY restaurant_id,r.name,r.country
name | country | Total_orders
:-------------- | :------- | -----------:
KFC | Pakistan | 4
McDonald's | Holland | 2
Howdy | Pakistan | 1
Kitchen Cuisine | Pakistan | 1
SELECT
MAX(r.name) name,
MAX(r.country) country,
COUNT(*) Total_orders
FROM
orders o JOIN restaurants r ON o.restaurant_id = r.id
WHERE YEAR(`date`)= 2021 AND MONTH(`date`)= 1
GROUP BY restaurant_id
name | country | Total_orders
:-------------- | :------- | -----------:
KFC | Pakistan | 4
McDonald's | Holland | 2
Howdy | Pakistan | 1
Kitchen Cuisine | Pakistan | 1
db<>fiddle here
SELECT -- MySQL SELECT statement
MAX(r.name) `Hotel Name`, -- column name as Hotel Name from table restaurants, alias as r
COUNT(*) `Number Of Orders`, -- count all the records for table orders, alias o
SUM(o.order_value) `Total Order Value`, -- SUM all the order_values for match records
MAX(r.country) `Country` -- column country
FROM
orders o -- Running operations on table orders and set alias o
INNER JOIN restaurants r ON o.restaurant_id = r.id -- INNER JOIN second table restaurants as r and joining
-- two tables using field r.id (restaurants primary key id)
-- and o.restaurant_id (foreign key of restaurant's primary key id)
WHERE -- setting condition
YEAR(o. `date`) = 2021 -- Year must be 2021
AND MONTH(o. `date`) = 1 -- and month must be JAN or 1
GROUP BY -- group all same hotels id
o.restaurant_id;
| Hotel Name | Number Of Orders | Total Order Value | Country |
|-----------------|------------------|-------------------|----------|
| KFC | 4 | 1544 | Pakistan |
| McDonald's | 2 | 622 | Holland |
| Howdy | 1 | 200 | Pakistan |
| Kitchen Cuisine | 1 | 250 | Pakistan |
HINT -
To join the two different tables we'd need two columns which has same values, common or has some linking.
Here table orders has restaurant_id which is a foreign key of table restaurants (id). In other word, we can use those id to identify the restaurant details by querying table restaurants.
hence to join table orders and restaurants, we should use column id from table restaurants and column restaurant_id from table orders.
Now since orders table has multiple rows with the same restaurant_id; it's better group them together to make as buckets.
Once we use GROUP BY a column; MySQL group them in a bucket which has same values or given conditions.
Any aggregated statement like SUM, AVG, COUNT, MAX, MIN, etc. would take those individual buckets as logical table and perform the operations.
I am trying to write a query to get the 3rd merchant with the highest lifetime
transaction amount. Also, I have to provide the total transactions to date for this
merchant.
This is the create table statement.
CREATE TABLE transaction(
transaction_id int , user_id int , merchant_name varchar(255), transaction_date date , amount int
);
INSERT INTO transaction(transaction_id, user_id, merchant_name, transaction_date, amount)
VALUES (1, 1 ,'abc', '2015-01-17', 100),(2, 2, 'ced', '2015-2-17', 100),(3, 1, 'def', '2015-2-16', 120),
(4, 1 ,'ced', '2015-3-17', 110),(5, 1, 'ced', '2015-3-17', 150),(6, 2 ,'abc', '2015-4-17', 130),
(7, 3 ,'ced', '2015-12-17', 10),(8, 3 ,'abc', '2015-8-17', 100),(9, 2 ,'abc', '2015-12-17', 140),(10, 1,'abc', '2015-7-17', 100),
(11, 1 ,'abc', '2015-01-17', 120),(12, 2 ,'ced', '2015-12-23', 130);
I am not sure how the o/p would look like. I am stuck here.
SELECT distinct(merchant_name), max(amount) from transaction
For MySQL, we could do this:
CREATE TABLE transaction (
transaction_id int , user_id int , merchant_name varchar(255), transaction_date date , amount int
);
INSERT INTO transaction(transaction_id, user_id, merchant_name, transaction_date, amount)
VALUES (1, 1 ,'abc', '2015-01-17', 100),(2, 2, 'ced', '2015-2-17', 100),(3, 1, 'def', '2015-2-16', 120),
(4, 1 ,'ced', '2015-3-17', 110),(5, 1, 'ced', '2015-3-17', 150),(6, 2 ,'abc', '2015-4-17', 130),
(7, 3 ,'ced', '2015-12-17', 10),(8, 3 ,'abc', '2015-8-17', 100),(9, 2 ,'abc', '2015-12-17', 140),(10, 1,'abc', '2015-7-17', 100),
(11, 1 ,'abc', '2015-01-17', 120),(12, 2 ,'ced', '2015-12-23', 130)
;
SELECT merchant_name
, SUM(amount) AS sum_amount
FROM transaction
GROUP BY merchant_name
ORDER BY sum_amount DESC
LIMIT 2, 1
;
Result:
+---------------+------------+
| merchant_name | sum_amount |
+---------------+------------+
| def | 120 |
+---------------+------------+
The full result without limiting, for comparison, is:
+---------------+------------+
| merchant_name | sum_amount |
+---------------+------------+
| abc | 690 |
| ced | 500 |
| def | 120 |
+---------------+------------+
Understanding the meaning of "lifetime transaction", playing with orders and limits, and two levels of aggregation, you can get what you want:
select t.merchant_name, count(*)
from transactions t
join (
select merchant_name, sum(amount) amount
from transactions
group by merchant_name
order by 2 desc
limit 3
) top3
on t.merchant_name = top3.merchant_name
group by t.merchant_name
order by top3.amount asc
limit 1
You can test on this db<>fiddle
If you had a "merchant" dimension, you could get the merchant_name from there and perform the sum and count in the same subquery, improving this way the query performance. Something like this...
select m.merchant_name, top3.amount, top3.nbtrans
from merchants m
join (
select merchant_name, sum(amount) amount, count(1) as nbtrans
from transactions
group by merchant_name
order by 2 desc
limit 3
) top3
on t.merchant_name = top3.merchant_name
order by top3.amount asc
limit 1
I have a table named 'reports', something like this:
id
user_id
type
customer_id
text
created_at
1
1
1
3
....
2021-08-07 17:00:52
2
1
1
3
....
2021-08-12 10:11:11
3
1
1
9
....
2021-08-12 10:08:14
4
1
2
3
....
2021-08-12 10:04:08
5
1
2
9
....
2021-08-13 20:32:21
6
2
1
7
....
2021-08-13 20:34:17
7
2
2
8
....
2021-08-14 18:55:09
I want to get the count of rows that a user has submitted type 1 reports that result in a type 2 report.
Type 1 report means reporting a phone call to the customer and type 2 means meeting the customer. I want to receive the number of calls that resulted in an meeting.
For example, for user 1 should returns 3, because for customer 3, IDs 1 and 2 have led to ID 4, and for customer 9, ID 3 has led to ID 5.
But for user 2, ID 7 is type 2 but there is no previous type 1 report for customer 8, so it returns 0.
Schema (MySQL v5.7)
CREATE TABLE reports
(id int auto_increment primary key,
user_id int,
type int,
customer_id int,
text varchar(4),
created_at varchar(19)
);
INSERT INTO reports
(id, user_id, type, customer_id, text, created_at)
VALUES
(1, 1, 1, 3, '....', '2021-08-07 17:00:52'),
(2, 1, 1, 3, '....', '2021-08-12 10:11:11'),
(3, 1, 1, 9, '....', '2021-08-12 10:08:14'),
(4, 1, 2, 3, '....', '2021-08-12 10:04:08'),
(5, 1, 2, 9, '....', '2021-08-13 20:32:21'),
(6, 2, 1, 7, '....', '2021-08-13 20:34:17'),
(7, 2, 2, 8, '....', '2021-08-14 18:55:09');
Query #1
SELECT x.user_id
, COUNT(DISTINCT y.id) total
FROM reports x
LEFT
JOIN reports y
ON y.id<=x.id
AND y.user_id = x.user_id
AND y.customer_id = x.customer_id
AND y.type = 1
WHERE x.type = 2
GROUP
BY x.user_id;
user_id
total
1
3
2
0
View on DB Fiddle
You haven't shown how your are expecting results, but simply refer to User 1 and 2 and the total votes, you can try using a lateral join
select user_id, Coalesce(Sum(valid),0) rowcount
from reports r
join lateral (
select
case when exists (select * from reports rr
where rr.user_id=r.user_Id and rr.type=2 and rr.customer_id=r.customer_Id and r.type=1)
then 1 end valid
)x
group by User_Id
Example Fiddle
First you Count the number of customers that comply with your criterioa type and typoe 2. But ti get all user you need to join the list of users
I used LEFT join as also RIGHt JOIN in my example
CREATE TABLE reports
(`id` int, `user_id` int, `type` int, `customer_id` int, `text` varchar(4), `created_at` varchar(19))
;
INSERT INTO reports
(`id`, `user_id`, `type`, `customer_id`, `text`, `created_at`)
VALUES
(1, 1, 1, 3, '....', '2021-08-07 17:00:52'),
(2, 1, 1, 3, '....', '2021-08-12 10:11:11'),
(3, 1, 1, 9, '....', '2021-08-12 10:08:14'),
(4, 1, 2, 3, '....', '2021-08-12 10:04:08'),
(5, 1, 2, 9, '....', '2021-08-13 20:32:21'),
(6, 2, 1, 7, '....', '2021-08-13 20:34:17'),
(7, 2, 2, 8, '....', '2021-08-14 18:55:09')
;
SELECT IFNULL(Counts,0),t1.user_id
FROM (SELECT COUNT(distinct r.customer_id) counts,user_id
FROM reports r
WHERE type = 1 AND EXISTS(SELECT 1 FROM reports WHERE type = 2 AND customer_id = r.customer_id)
GROUP BY user_id) r RIGHT JOIN (SELECT DISTINCT user_id FROm reports) t1 ON r.user_id = t1.user_id
IFNULL(Counts,0) | user_id
---------------: | ------:
2 | 1
0 | 2
SELECT IFNULL(Counts,0),t1.user_id
FROM (SELECT DISTINCT user_id FROm reports) t1 LEFT JOIN (SELECT COUNT(distinct r.customer_id) counts,user_id
FROM reports r
WHERE type = 1 AND EXISTS(SELECT 1 FROM reports WHERE type = 2 AND customer_id = r.customer_id)
GROUP BY user_id) r ON r.user_id = t1.user_id
IFNULL(Counts,0) | user_id
---------------: | ------:
2 | 1
0 | 2
db<>fiddle here
My sql looks like:
create table ad(
ad_id int,
ad_name varchar(10)
);
insert into ad(ad_id, ad_name) values
(1,'ad1'),
(2,'ad2'),
(3,'ad3');
create table ad_insight(
id int,
ad_id int,
date date,
clicks int
);
insert into ad_insight(id, ad_id, date, clicks) values
(1, 1, '2021-04-25', 1),
(2, 1, '2021-04-24', 4),
(3, 1, '2021-04-23', 2),
(4, 2, '2021-04-25', 6),
(5, 2, '2021-03-03', 7);
create table product(
product_id int,
product_name varchar(10)
);
insert into product(product_id, product_name) values
(1,'prod1'),
(2,'prod2'),
(3,'prod3'),
(4,'prod4'),
(5,'prod5');
create table product_insight(
id int,
product_id int,
sale int,
date date
);
insert into product_insight(id, product_id, sale, date) values
(1, 1, 12, '2021-04-25'),
(2, 1, 11, '2021-04-24'),
(3, 1, 13, '2021-04-23'),
(4, 1, 14, '2021-04-22'),
(5, 1, 17, '2021-04-21'),
(6, 1, 15, '2021-04-20'),
(7, 1, 13, '2021-04-19'),
(8, 2, 19, '2021-04-25');
create table ads_products(
ad_id int,
product_id int
);
insert into ads_products (ad_id, product_id) values
(1, 1),
(1, 2),
(2, 3),
(2, 4),
(1, 3);
Here you have fiddle
A quick explanation of schema:
I have ads:
each ad has insights, which tell us when a certain ad was active.
each ad has products(many2many - ads_products table). Each product has product_insight which tells us how many sales that product generated on a certain day.
And now I want to get the following table which will sum up clicks from ad_insight table and sum up product_sale from product_insight in 2021-04-23 to 2021-04-25 inclusive.
+----------+--------+--------------+--------------+
| ad_name | clicks | product_sale | products |
+----------+--------+--------------+--------------+
| ad1 | 7 | 55 | prod1, prod2 |
| ad2 | 6 | 0 | prod3, prod4 |
| ad3 | 0 | 36 | prod1 |
+----------+--------+--------------+--------------+
What I have tried?
select ad_name, SUM(ad_insight.clicks) as clicks
from ad
left join ad_insight on ad.ad_id = ad_insight.ad_id
where ad_insight.date >= '2021-04-23' and ad_insight.date <= '2021-04-25'
group by ad.ad_id;
But I do not know how to select product_sale table and products separated by a comma?
Hey I have run into a problem - I thought it would be easy with just group by but it was a little more when time is a factor in the game.
I'm trying to get all the records on different mainQuestion_id which can have duplicates with different timestamp (and id ofc). This should be filtered so I get those which are equal to an activationCode_id and not with a subquestion which is the field subQuestion_id
So lets say I have this table
CREATE TABLE surveys_answer
(`id` int, `activationCode_id` int, `mainQuestion_id` int, `subQuestion_id` int, `timestamp` int);
INSERT INTO surveys_answer
(`id`, `activationCode_id`, `mainQuestion_id`, `subQuestion_id`, `timestamp`)
VALUES
(1, 1, 4, 0, 201313),
(2, 1, 4, 0, 201314),
(3, 2, 3, 1, 201315),
(4, 2, 4, 0, 201316),
(5, 1, 9, 1, 201317),
(6, 1, 6, 0, 201318),
(7, 1, 4, 1, 201319);
and I want the results which are latest by time or id which have activationCode_id = 1 and where subQuestion_id = 0
what I want is
2, 1, 4, 0, 201314
6, 1, 6, 0, 201318
I have been trying with group by, that misses (2, 1, 4, 0, 201314) and takes the first one (1, 1, 4, 0, 201313) which is not what I want
I thought this would work:
SELECT * FROM surveys_answer
WHERE activationCode_id = 1
AND subQuestion_id = 0
group by mainQuestion_id
I have been trying to get this to work:
SELECT a.*
FROM surveys_answer a
INNER JOIN
(
SELECT max(id) xx, mainQuestion_id
FROM surveys_answer
GROUP BY mainQuestion_id
) b ON a.mainQuestion_id = b.mainQuestion_id AND
a.id = b.xx AND a.activationCode_id = '1' AND a.subQuestion_id = 0
But this gives me zero results
http://www.sqlfiddle.com/#!2/3e1cd
Can some one help me out with this?
SELECT sa.*
FROM surveys_answer sa
WHERE timestamp = (
SELECT MAX(sa2.timestamp)
FROM surveys_answer sa2
WHERE sa2.activationCode_id = 1 AND sa2.subQuestion_id = 0 AND
sa2.mainQuestion_id = sa.mainQuestion_id
);
SQL Fiddle
Result based on your sample data:
| ID | ACTIVATIONCODE_ID | MAINQUESTION_ID | SUBQUESTION_ID | TIMESTAMP |
|----|-------------------|-----------------|----------------|-----------|
| 2 | 1 | 4 | 0 | 201314 |
| 6 | 1 | 6 | 0 | 201318 |
may be you can try this
SELECT surveys_answer .* , max(timestamp) as mx_time FROM surveys_answer
WHERE activationCode_id = 1
AND subQuestion_id = 0
group by timestamp