Hi i am a newbie to SQL and have one doubt on comparing different products across multiple tables.
I have 3 tables
T1:
Product_type
order_id
T2 and T3 also has the same fields.
All the tables have different product types. They may or may not have same order ids. Its like you can order product p1 from T1 and product p2 from T2 together on the same order id o1 or they can be separate orders.
I want to find the number of orders where product type(p1) from T1 and product type(p2) from T2 are ordered in the same order(having the same order id).
I am trying to run the query like this :
select COUNT(DISTINCT order_id) as CountOf from
(
select product_type from t1
UNION ALL select product_type from t2
)
AS m
where t1.product_type = p1 and t2.product_type = p2;
What i figured out is that i cannot access t1 and t2 in the outer query since they are used in the inner query. So is there a way i can make comparision between products?
Any help would be greatly appreciated.
Thank you
Try this:
select
count(distinct t1.order_id) as OrderCount
from
t1
inner join
t2 on t1.order_id = t2.order_id
where
t1.product_type = 'p1' and
t2.product_type = 'p2'
I can't understand what you want.
But inner query scope to brackets only. So you can not access outside to brackets. try to this
select COUNT(DISTINCT order_id) as CountOf from
(
select DISTINCT order_id from t1
where t1.product_type = p1
UNION ALL
select DISTINCT order_id from t2
where t2.product_type = p2
) m
Related
In MySQL, how would you re-write a SELECT query which JOIN SELECT subqueries that are doing almost the same thing.
In my case, I am getting performance issues because in the subqueries, I need to join on the same tables for each subqueries which is an heavy operation.
Consider the below (ugly) example:
set #businessdate = '2020-01-24';
Select Daily.*, Monthly.Price, Yearly.Price FROM
# DAILY
(Select #businessdate as BusinessDate, t1.Owner , SUM(t.Price) AS DailyPrice
FROM Table t
INNER JOIN Table2 t2 on ...
INNER JOIN Table1 t1 on ...
where t2.date = #businessdate
GROUP BY t1.Owner) Daily
INNER JOIN
# MONTHLY
(Select SUM(t.Price) AS Price, t1.Owner
FROM Table t
INNER JOIN Table2 t2 on ...
INNER JOIN Table1 t1 on ...
where MONTH(t2.date) = MONTH(#businessdate) and YEAR(t2.date) = YEAR(#businessdate)
GROUP BY t1.Owner) Monthly
INNER JOIN
#YEARLY
(Select SUM(t.Price) AS Price, t1.Owner
FROM Table t
INNER JOIN Table2 t2 on ...
INNER JOIN Table1 t1 on ...
where YEAR(t2.date) = YEAR(#businessdate)
GROUP BY t1.Owner) Yearly
The reason is I need the date in my where clause (coming from t2), and one field in my group by coming from t1. I also need to display some fields from t1.
I only need the SUM(Price) (the Price from Monthly and Yearly...) so to me it sounds like the joins in subqueries is overkill even if it is working fine (very slow...)
You could use conditional aggregation with a single query:
Select
#businessdate as BusinessDate, ... ,
SUM(CASE WHEN t2.date = #businessdate THEN t.Price ELSE 0 END) AS DailyPrice,
SUM(CASE WHEN MONTH(t2.date) = MONTH(#businessdate) AND
YEAR(t2.date) = YEAR(#businessdate)
THEN t.Price ELSE 0 END) AS MonthlyPrice,
SUM(CASE WHEN YEAR(t2.date) = YEAR(#businessdate)
THEN t.Price ELSE 0 END) AS AnnualPrice
FROM Table t
INNER JOIN Table2 t2 on ...
INNER JOIN Table1 t1 on ...
GROUP BY t1.Owner
This at least would allow you to avoid unneeded passes over the joined tables. Note that your GROUP BY clause is invalid as written; the business date is the only valid single column which can be selected, other than the conditional sums.
SELECT t1.name as r_name, t1.values as r_values
FROM table as t1
JOIN (
SELECT SUM(amount) as amount
FROM database2.table
WHERE ids IN (t1.values)
) as t2
WHERE t1.id = 20;
I get an error, that t1.values inside the subquery is unknown column.
You need to rewrite your query and take inne where to join condition:
SELECT t1.name as r_name, t1.values as r_values
FROM table as t1
JOIN (
SELECT SUM(amount) as amount
FROM database2.table
) as t2 ON t2.ids = t1.values
WHERE t1.id = 20;
Also, you don't use amount column, so what is the point of join?
Another issue, you don't have any join condition defined.
I think you need to read about joins in SQL first :)
It seems you are trying to join database2.table to your t1 based on t1.values list.
I added group by IDs in t2 since your using aggregation function. Then, not sure what's the purpose of your sum(amount)
SELECT t1.name as r_name, t1.values as r_values
FROM table as t1
JOIN (
SELECT SUM(amount) as amount, ids
FROM database2.table
GROUP BY ids
) as t2 on t2.ids IN (t1.values)
WHERE t1.id = 20;
I was not sure how to phrase my question as I am new to SQL. It should not be too hard. Here is the scenario.
I have 3 tables:
customers
id,
contact
subscribers_from_x
customer_id
subscriber_name
subscribers_from_y
customer_id,
subscriber_name
here is the question:
Now, I want to select
customer.id
the number of times/count of customer.id occurs in subscribers_from_x
the number of times/count of customer.id occurs in subscribers_from_y
from these 3 tables
I have tried GROUP_BY COUNT(*) but not figuring it out. THanks
I might go with using two separate subqueries which aggregate counts by subscriber for the x and y tables:
SELECT t1.id,
t1.contact,
COALESCE(t2.x_count, 0) AS subscribers_from_x,
COALESCE(t3.y_count, 0) AS subscribers_from_y
FROM customers t1
LEFT JOIN
(
SELECT customer_id, COUNT(*) AS x_count
FROM subscribers_from_x
GROUP BY customer_id
) t2
ON t1.id = t2.customer_id
LEFT JOIN
(
SELECT customer_id, COUNT(*) AS y_count
FROM subscribers_from_y
GROUP BY customer_id
) t3
ON t1.id = t3.customer_id
SELECT DISTINCT(users.id),count(x.customer_id) 'X count',count(y.customer_id) 'Y Count'
FROM customers
LEFT JOIN subscribers_from_x x ON customers.id = x.customer_id
LEFT JOIN subscribers_from_y y ON customers.id = y.customerid
GROUP BY customers.id,subscribers_from_x.pk_col -- primary key col of subscribers_from_x
It will give you required output
I am writing a mysql query and I have a question. Can I / How do I do something like this:
select rating, user_id, (
-- in here I want to write a subquery to get the number of times the user_id in the outter query has rated this teacher
) as user_rated_frequency from teachers_rating where teacher_id = id
Essentially I am trying to get data and the frequency in which that user rated that teacher. Is it possible to use an alias from one of the items I want to select in a subquery that is still in the select and not in the where clause?
Check out this ...
SELECT rating,
user_id,
(SELECT COUNT(*)
FROM teachers_rating t1
WHERE teacher_id = 3
AND t1.user_id = t2.user_id) AS user_rated_frequency
FROM teachers_rating t2
WHERE teacher_id = 3;
or that one:
SELECT AVG (rating) AS average_rating,
user_id,
(SELECT Count(*)
FROM teachers_rating t1
WHERE teacher_id = 3
AND t1.user_id = t2.user_id) AS user_rated_frequency
FROM teachers_rating t2
WHERE teacher_id = 3
GROUP BY user_rated_frequency;
Links above show a SQL Fiddle example assuming that id is 3.
Alternatively you could have a sub query in the FROM clause:
SELECT AVG (t1.rating),
t1.user_id,
t2.user_rated_frequency
FROM teachers_rating t1,
(SELECT tr.teacher_id,
tr.user_id,
COUNT(*) AS user_rated_frequency
FROM teachers_rating tr
GROUP BY tr.teacher_id) t2
WHERE t1.teacher_id = t2.teacher_id
AND t1.user_id = t2.user_id
GROUP BY user_id, user_rated_frequency
Hat a look at this Fiddle.
You need to move your subquery (technically called a derived table) into your from clause.
Something like so:
select
rating,
user_id,
from teachers_rating,
(in here I want to write a subquery to get the number of times the user_id in the outter query has rated this teacher) as user_rated_frequency f
where teacher_id = f.id
I have 2 tables:
Table1 => product_id, product_quantity => here I have 25 rows.
Table2 => product_hashid, order_quantity => here I have 1 query row.
I build this mysql query:
SELECT SUM(table1.product_quantity) - SUM(order_quantity) AS instocks
FROM table1 -- table.1 in original
LEFT JOIN table2 ON table2.product_hashid = table1.product_id
WHERE table1.product_id = '$thisid'
This query duplicates table2 row with table1. Is there some error in this query?
First, I want to sum all product_quantity from table1 where product_id = '$this' and sum all order_quantity in table2 where product_hashid = '$this' and make (a - b) to display a final result.
Your outline of what you want to do is good, but it isn't what you implemented.
I want to sum all product_quantity from table1 where product_id = '$this' and sum all order_quantity in table2 where product_hashid = '$this' and make (a - b) to display a final result.
Build it up one step at a time.
SELECT SUM(product_quantity) FROM Table1 WHERE Product_ID = '$this';
SELECT SUM(order_quantity) FROM Table2 WHERE Product_HashID = '$this';
SELECT (SELECT SUM(product_quantity) FROM Table1 WHERE Product_ID = '$this') -
(SELECT SUM(order_quantity) FROM Table2 WHERE Product_HashID = '$this')
FROM Dual;
You might observe that the code alignment emphasizes the inconsistent column naming for the product ID columns.
In the more general case:
SELECT Product_ID, SUM(product_quantity) AS Product_Quantity
FROM Table1
GROUP BY Product_ID;
SELECT Product_HashID AS Product_ID, SUM(order_quantity) AS Order_Quantity
FROM Table2
GROUP BY Product_HashID;
SELECT p.Product_ID, p.Product_Quantity - o.Order_Quantity AS SurplusOnHand
FROM (SELECT Product_ID, SUM(product_quantity) AS Product_Quantity
FROM Table1
GROUP BY Product_ID) AS P
JOIN (SELECT Product_HashID AS Product_ID, SUM(order_quantity) AS Order_Quantity
FROM Table2
GROUP BY Product_HashID) AS O
ON O.Product_ID = P.Product_ID;
Sometimes you need to use a LEFT OUTER JOIN; mostly, you don't. Write your SQL assuming you don't until you're sure that you do.
Given the data cardinalities (row counts), you may need to do an LOJ here. You need to manufacture a zero for the order quantity of those products listed in Table1 that are not listed in Table2.
SELECT (SELECT SUM(product_quantity) FROM Table1 WHERE Product_ID = '$this') -
NVL(SELECT SUM(order_quantity) FROM Table2 WHERE Product_HashID = '$this'), 0)
FROM Dual;
SELECT p.Product_ID, p.Product_Quantity - NVL(o.Order_Quantity, 0) AS SurplusOnHand
FROM (SELECT Product_ID, SUM(product_quantity) AS Product_Quantity
FROM Table1
GROUP BY Product_ID) AS P
LEFT OUTER JOIN
(SELECT Product_HashID AS Product_ID, SUM(order_quantity) AS Order_Quantity
FROM Table2
GROUP BY Product_HashID) AS O
ON O.Product_ID = P.Product_ID;
LEFT JOIN will return all of table1 in every case.
http://www.w3schools.com/sql/sql_join_left.asp
Do you actually want just the products in table1 if they appear in table 2? If so, you need simply JOIN (or INNER JOIN)
http://www.w3schools.com/sql/sql_join_inner.asp
I think the issue is your JOIN and your WHERE clause. In this setup, you will return all of the data from table2, which will give you a mess. Your WHERE clause is looking at table1 and limiting the rows there but your JOIN returns all rows from table2 and only those rows from table1 that are equal.
Bottom line: change your join to be an INNER JOIN and your problems will go away.