Aggregate data for 2 tables sql - sql

I have 2 questions which I was unable to answer in an interview, and hence do not have the answer.
2 questions are:
a. Write a query to get close rate by make and partner name (close rate = sales count / lead count)
Attempt:
select (totalsales/totalleads) as close_rate
(select count(sale_id) as totalsales from daily_sales group by make_name) S
outer join
(select count(lead_id) as totalleads from daily_leads group by make_name) L
on S.make_name=L.make_name
outer join
(select partner_name from partners) P
on L.partner_id=P.partnerid
b. Write a query to Aggregate data to get daily leads and sales count by make and date
Attempt:
select count(sale_id), count(lead_id)
from daily_leads dl
full outer join
on daily_sales ds
on dl.lead_id=ds.lead_id
group by make_name, date
TABLES:
Daily_Leads
+---------------------------------------------------+
| lead_id partner_id date_id make_name |
+---------------------------------------------------+
| 4 2 2019-01-01 toyota |
| 6 2 2019-01-01 honda |
| 8 2 2019-01-02 toyota |
| 9 70 2019-01-01 honda |
| 2 70 2019-01-01 ford |
| 7 1 2019-01-01 bmw |
| 10 4 2019-01-01 bmw |
| 25 1 2019-01-02 ford |
| |
+---------------------------------------------------+
Table Name: daily_sales
+-----------------------------------------------------------------+
| lead_id partner_id date_id make_name Sale_id |
+-----------------------------------------------------------------+
| 4 2 2019-01-01 toyota 1 |
| 6 2 2019-01-01 honda 2 |
| 8 2 2019-01-02 toyota 3 |
| 9 70 2019-01-02 honda 4 |
| 10 4 2019-01-01 bmw 5 |
+-----------------------------------------------------------------+
Table name partners
+----------------------+
| id partner_name |
+----------------------+
| 1 True |
| 2 App |
| 4 Way |
| 70 Fbook |
+----------------------+
I am trying outer joins which I know is probably wrong. Can someone please help me out?
I am new to StackOverFlow community, so I might not have a proper approach to asking questions. I am learning. Would be great if someone can answer these questions.

I guess that you can use the query joining two aggregate queries.
For a., the query is below:
select
M.make_name,
P.partner_name,
L.totalleads,
S.totalsales,
S.totalsales/L.totalleads as close_rate
from
(select distinct make_name, partner_id from daily_leads
union select distinct make_name, partner_id from daily_sales) M
left outer join
(select make_name, partner_id, count(lead_id) as totalleads
from daily_leads
group by make_name, partner_id) L
on M.make_name=L.make_name and M.partner_id=L.partner_id
left outer join
(select make_name, partner_id, count(sale_id) as totalsales
from daily_sales
group by make_name, partner_id) S
on M.make_name=S.make_name and M.partner_id=S.partner_id
left outer join partners P
on M.partner_id=P.id;
db fiddle
For b., it's similar to a query that changed partner_id to date_id of the a. query.

Related

How can I SELECT MAX(VALUE) from duplicate values which occur multiple time within each month?

I have records for each user which occur multiple times each month. I wish to select just the highest value from the repeated values for each month for each user.
Table schema
custacc
ID | ac_no | DODSTART | od_limit
---+--------+------------+----------
1 | 110011 | 2019-02-10 | 200,000
2 | 110011 | 2019-02-12 | 120,000
3 | 110014 | 2019-02-10 | 70,000
4 | 110014 | 2019-02-12 | 10,000
5 | 110009 | 2019-02-10 | 30,000
customer
ID | cust_no | name | cust_type
---+---------+-------+----------
1 | 110011 | Jame | M
2 | 110014 | Fred | N
3 | 110009 | Ahmed | M
How can I achieve this>
What I tried so far:
SELECT
custacc.ac_no,
custacc.od_limit,
custacc.DODSTART,
customer.name,
custacc.gl_no,
custacc.USERNAME,
customer.cust_type
FROM
custacc
LEFT JOIN
customer ON custacc.ac_no = customer.cust_no
INNER JOIN
(SELECT
MAX(DODSTART) LAST_UPDATE_DATE_TIME,
ac_no
FROM
custacc
GROUP BY
ac_no) s2 ON custacc.ac_no = s2.ac_no
AND custacc.DODSTART = s2.LAST_UPDATE_DATE_TIME
WHERE
custacc.od_limit != 0.00
The query doesn't return the expected result.
Try this(add columns that you need):
This is Oracle solution since you didn't mention it in your question:
SELECT ID,MAX(OD_LIMIT) OVER(PARTITION BY ID,EXTRACT(MONTH FROM DODSTART)) FROM CUSTACC;

Trying to join a table of individuals to a table of couples, give a family ID and not time out the server

I have one table with fake individual tax records like so (one row per filer):
T1:
+-------+---------+---------+
| Person| Spouse | Income |
+-------+---------+---------+
| 1 | 2 | 34000 |
| 2 | 1 | 10000 |
| 3 | NULL | 97000 |
| 4 | 6 | 11000 |
| 5 | NULL | 25000 |
| 6 | 4 | 100000 |
+-------+---------+---------+
I have a second table which has tax 'families', a single individual or married couple (one line per tax 'family').
T1_Family:
+-------- -+-------+---------+
| Family_id| Person| Spouse |
+-------- -+-------+---------+
| 2 | 2 | 1 |
| 3 | 3 | NULL |
| 5 | 5 | NULL |
| 6 | 6 | 4 |
+------ ---+-------+---------+
Family = max(Person) within a couple
The idea of joining the two is for example, to sum the income of 2 people in one tax family (aggregate to the family level).
So, I've tried the following:
select *
into family_table
from
(
(select * from T1_family)a
join
(select * from T1)b
on a.family = b.person **or a.spouse = b.person**
)
where family_id is not null and person is not null
What I should get (and I do get when I select 1 random couple) is one line per individual where I can then group by family_id and sum income, pension contributions, etc. BUT SQL times out before the tables can be joined. The part in bold is what's slowing down the process but I'm not sure what else to do.
Is there an easier way to group by family?
It is simpler to put the data on one row:
select a.*, p.income as person_income, s.income as spouse_income
into family_table
from t1_family a left join
t1 p
on a.person = p.person lef tjoin
t1 s
on a.spouse = s.person;
Of course, you can add them together as well.

Relational database - adding products

I have the following situation, namely I need to make a database,
in which I will store products that the user added to breakfast,
lunch, midday meal and dinner ON A SPECIFIC DAY.
I have a problem with the construction of such a relational database.
I currently have this combination of two tables:
It seems to me that I need 3 tables here in which
the products themselves will be placed, but I have no idea how
I can combine these 3 tables to get queries
products depending on the type of meal (breakfast, lunch ..) and date (the day they were added)
Yes, you should have a Products table that should have the 5 last columns you are showing in your second table (Orders?). And remove them from the Orders table such that it only has the IDs referencing the Meal and Product and the Date.
Then you can do the following:
SELECT o.Date, m.Meal_Name, p.Product_Name, p.Carbohydrates,
p.Protein, p.Fat, p.Calories
FROM Orders o
INNER JOIN Meals m ON o.MealID = m.MealID
INNER JOIN Products p ON o.ProductID = p.ProductID
ORDER BY o.date, m.Meal_Name, p.Product_Name
Note that this will allow you to easly change the parameters (such as fat or Carbohydrates for a Product and have it appear in all records for that product.
While there is certainly plenty of room to interpretation here and you may only want to go so far in normalizing your data, I think a better option would be:
meals:
id | user_id | category_id | date
1 | 1 | 1 | 2019-09-03
meal_category
id | name
1 | breakfast
2 | lunch
3 | dinner
products
id | name | carbs | protein | fat | calories
1 | apple| 10 | 5 | 0 | 30
2 | cat | 0 | 20 | 5 | 80
3 | ham | 10 | 30 | 10 | 160
meal_products
meal_id | product_id
1 | 1
1 | 2
Bringing this together:
SELECT meals.id, meals.user_id, meal.date, meal_category.name, product.name, product.carbs, products.protein, products.fat, products.calories
FROM meals
INNER JOIN meal_category ON meals.category_id = meal_category.id
INNER JOIN meal_produts ON meals.id = meal_products.meal_id
INNER JOIN products ON meal_products.product_id = products.id
Which would yeild
+-----------+----------------+------------+---------------------+---------------+----------------+-------------------+---------------+-------------------+
| meals.id, | meals.user_id, | meal.date, | meal_category.name, | product.name, | product.carbs, | products.protein, | products.fat, | products.calories |
+-----------+----------------+------------+---------------------+---------------+----------------+-------------------+---------------+-------------------+
| 1 | 1 | 9/3/2019 | breakfast | apple | 10 | 5 | 0 | 30 |
| 1 | 1 | 9/3/2019 | breakfast | cat | 0 | 20 | 5 | 80 |
+-----------+----------------+------------+---------------------+---------------+----------------+-------------------+---------------+-------------------+

Cross Join is creating a Loop

I have three tables, I need to make a CROSS JOIN between them to display the IDs and names of the products and the stores that sell them, here is an example of how now
TABLE_PRODUCT
ID_PRODUCT | NAME_PRODUCT
1 | Addidas Super Star
2 | Calvin Klein BAG
TABLE_STORE
ID_STORE | NAME_STORE
1 | ThE 98
2 | C&A
TABLE_PROD_STOR
ID_STORE | ID_PROD
1 | 1
2 | 2
And I need the result in the format:
ID STORE | STORE | ID PRODUCT | PRODUCT |
1 | ThE 98 | 1 | Addidas Super Star |
2 | C&A | 2 | CALVIN KLEIN HAT |
My biggest problem is that when I do the CROSS JOIN, the names are repeated twice each. What is the solution?
Select
y.ID_STORE ,
y.NAME_STORE store ,
x.ID_PRODUCT,
x.NAME_PRODUCT product
from
TABLE_PRODUCT x inner join
TABLE_STORE y
on x.ID_PRODUCT =y.ID_STORE
inner join TABLE_PROD_STOR z
on x.ID_PRODUCT =z.ID_STORE

how to sql query 2 tables and group by?

i have 2 tables: activities and users.
users has columns: name, active
activities: name, type, time, user_id.
for example i have these tables:
users
-----
id | name | active
1 | marc | true
2 | john | true
3 | mary | true
4 | nico | true
activities
-----
id | name | type | time | user_id
1 | morn | walk | 90 | 2
2 | morn | walk | 22 | 2
3 | morn | run | 12 | 2
4 | sat | walk | 22 | 1
5 | morn | run | 13 | 1
6 | mond | walk | 22 | 3
7 | morn | walk | 22 | 2
8 | even | run | 42 | 1
9 | morn | walk | 22 | 3
10 | morn | walk | 62 | 1
11 | morn | run | 22 | 3
now i would like to get table that would sum time spent on each type of activity and would group it by user name. so:
result
------
user name | type | time
marc | walk | 84
marc | run | 55
john | walk | 134
john | run | 12
mary | walk | 44
mary | run | 2
nico | walk | 0
nico | run | 0
how should i write this query to get this result?
thanks in advance
gerard
you can use coalesce to get 0 for empty activities and distinct to get all type of possible activities
select
u.name, c.type,
coalesce(sum(a.time), 0) as time
from (select distinct type from activities) as c
cross join users as u
left outer join activities as a on a.user_id = u.id and a.type = c.type
group by u.name, c.type
order by u.name, c.type
sql fiddle demo
Select u.name, a.type, SUM(a.time) FROM
activities a
LEFT JOIN users u
ON a.user_id = u.id
GROUP BY u.name, a.type
FIDDLE
Use this to get zero count as well
SELECT c.name,c.type,aa.time FROM
(Select u.id,u.name, b.type FROM
users u
CROSS JOIN (SELECT DISTINCT type FROM activities) b) c
LEFT JOIN (SELECT a.user_id, a.type, SUM(a.time) as time FROM
activities a
GROUP BY a.user_id, a.type) aa ON
aa.user_id = c.id and c.type = aa.type
Fiddle2
this might work :
select users.name,activities.type,sum(activities.time)
from users left join activities on users.id = activities.user_id
where users.active group by users.name,activities.type