SQL - Order By Sum of Multiple Tables Sharing Common Field - mysql

I have 2 different tables sharing the same column names. The tables list the same products which are identified by 'id'. The products have different revenues throughout both tables and are listed multiple times in each table.
I would like to sum the revenue of the same products across the 2 tables and ORDER BY the sum. Result is sorting the highest revenue products first.
I've tried JOIN and UNION but can't seem to figure out the right solution.
UNION query I tried...
SELECT id, SUM(rev) as total
FROM (
SELECT id, rev FROM table1 UNION ALL
SELECT id, rev FROM table2 UNION ALL
)
ORDER BY total DESC
JOIN query I tried...
SELECT table1.id,
table1.rev,
table2.id,
table2.rev,
(table1.rev + table2.rev) as revenue
FROM table1
INNER JOIN table2 ON table1.id = table2.id
ORDER BY revenue DESC

You were close. You needed:
one UNION ALL, not two.
a GROUP BY, that gives the break field.
An alias for the subquery (I used AllRevenue - you can use any valid name.)
SELECT id, SUM(rev) as total
FROM (
SELECT id, rev FROM table1 UNION ALL
SELECT id, rev FROM table2
) AS AllRevenue
GROUP BY id
ORDER BY total DESC
The join approach would have worked if you used a FULL OUTER JOIN, because some ids may be present in one table but not the other, but that is usually less performant.

Looks like you just need to group on the ID then... unless I'm missing something.
select d.* from (
SELECT
table1.id,
Sum(table1.rev) + Sum(table2.rev) as revenue
FROM table1
INNER JOIN table2 ON table1.id = table2.id
GROUP BY
table1.id) d
order by d.revenue

SELECT id, SUM(rev) as total
FROM (
SELECT id, rev FROM table1 UNION ALL
SELECT id, rev FROM table2
)
GROUP BY id
ORDER BY total DESC

Related

Divide count by average in SQL from three different tables

I have three tables and I am using counts from each tables to get a rate%.
This is the formula and I am trying to replicate it using MySQL
Count1.t1/AVERAGE(Count2.t2,Count3t.3)
So far the average is working and this is what I have:
This code block gives me the average between t1 and t2.
SELECT AVG(ID.TAvg) FROM ( select count(*) as TAvg from t2 UNION Select count(*) as TAvg from t3) ID;
However, if I divide t1 count with the average it breaks.
(SELECT COUNT(ID) from t1) / (SELECT AVG(ID.TAvg) FROM ( select count(*) as TAvg from t2 UNION Select count(*) as TAvg from t3) ID);
Can anyone please help with this? I am basically trying to get a count from one table and divide it with an average from two separate tables. I appreciate the help.
Your:
(SELECT COUNT(ID) from t1) / (SELECT AVG(ID.TAvg) FROM ( select count(*) as TAvg from t2 UNION Select count(*) as TAvg from t3) ID)
is the value you want, but it is an expression, not a select. You can just add a select:
SELECT (SELECT COUNT(ID) from t1) / (SELECT AVG(ID.TAvg) FROM ( select count(*) as TAvg from t2 UNION Select count(*) as TAvg from t3) ID)
or do the divide in the from t1:
SELECT COUNT(ID) / (SELECT AVG(ID.TAvg) FROM ( select count(*) as TAvg from t2 UNION Select count(*) as TAvg from t3) ID) from t1
(Though you don't say what "it breaks" actually means; do you in fact have an ID column in t1 and want to count rows where ID is not null? If you just want to count all rows in t1, do count(*) or count(1), not count(ID).)
One other thing: UNION means UNION DISTINCT, which removes duplicate rows after unioning (as opposed to UNION ALL which just unions the rows from the two queries). Since you are just averaging two tables, there is no problem, but if you were summing, or averaging three tables, there would be. For instance, if you were averaging 3, 3, and 6, with UNION ALL, that would produce 4, but with UNION DISTINCT, it first becomes just 3 and 6, producing an average of 4.5. You almost always want to say UNION ALL, not just UNION.

Selecting row with max date from multiple almost identical tables

If I can retrieve the most recent name for each id from a table in a MySQL database like so:
SELECT n.id, n.name, n.date
FROM $table AS n
INNER JOIN
(SELECT id, MAX(date) AS date
FROM $table GROUP BY id)
AS max
USING (id, date);
How could I retrieve the most recent name from three almost identical tables (call them $table, $table2, $table3)? They all share the same column structure and the id found from one table may or may not be present in the other two. Think of it as one large table split into three (but with two of them containing two extra columns that are irrelevant in this instance). Would UNION be the best solution? If so, is there a way to do it without a mile-long query?
Constraint:
id is not an auto-incrementing unique integer unfortunately
You can use union all. One slight simplification is the group_concat()/substring_index() trick:
select id, max(date) as date,
substring_index(group_concat(name order by date desc), ',', '') as MostRecentName
from (select t.* from $table1 t union all
select t.* from $table2 t union all
select t.* from $table3
) t
group by id;
This does make certain assumptions. The name cannot contain , (although it is easy enough to change the separator. In addition, the intermediate result for the group_concat() cannot exceed a certain threshold (which is determined by a user-settable system parameter).
You could try:
SELECT n.id, n.name, n.date
FROM table1 where id in (select max(id) from table1)
union
SELECT n.id, n.name, n.date
FROM table2 where id in (select max(id) from table2)
union
SELECT n.id, n.name, n.date
FROM table3 where id in (select max(id) from table3)
Every inner query selects the highest id from the table and then searches for the corresponding fields in the outer query.
This ended up being the only solution I could think of:
SELECT n.id, n.name, n.date FROM (
SELECT id, name, date FROM $table
UNION ALL
SELECT id, name, date FROM $table2
UNION ALL
SELECT id, name, date FROM $table3
) AS n INNER JOIN (
SELECT id, MAX(date) AS date FROM (
SELECT id, date FROM $table
UNION ALL
SELECT id, date FROM $table2
UNION ALL
SELECT id, date FROM $table3
) AS t
GROUP BY id
) AS max USING (id, date)

How to select * from table when group by?

select
OrderNo,
Sum(QtyIn) as QuantityIn,
Sum(QtyOut) as QuantityOut
from
tbl_Assign
group by
OrderNo
I want to select * from table also group by from table. How to do it?
To group by on all columns with a sum you cannot use *, you have to list all of the columns out and every column that isn't a function like Sum must be included in the group by.
So if you have other fields in your database such as OrderName, OrderedBy you can perform a group by like this:
Select
OrderNo,
OrderName,
OrderBy,
Sum(QtyIn) as QuantityIn,
Sum(QtyOut) as QuantityOut
From
tbl_Assign
Group By
OrderNo, OrderName, OrderBy
The following will create one row for every row in the tbl_Assign.
Each row will also show the summary information for the order.
This might not be what you need, but it's useful to understand it anyway.
SELECT T1.*, T2.*
FROM
( select * FROM tbl_Assign ) AS T1
LEFT JOIN ( select
OrderNo,
Sum(QtyIn) as QuantityIn,
Sum(QtyOut) as QuantityOut
from
tbl_Assign
group by
OrderNo
) AS T2
ON T1.OrderNo = T2.OrderNo
Harvey

Avoiding duplicates in mysql query that uses UNION and ORDER BY

I have two tables, lets say table1 and table2 with common columns, id and update_date. I am looking to get the id's and update_date based on latest update_date in descending order. I have used 'union' and 'order by' together which gave the results in descending order of update_date but there are duplicate id's which I am not sure how to get rid of.
My query is like,
(select id,update_date from table1 where [condition])
UNION
(select id,update_date from table2 where [condition])
order by update_date desc;
I can just get rid of the duplicate id's by adding select distinct id from (above query) as temp; but the problem is that I need the update_date too.
Can anyone suggest how to get rid of duplicates and still get both id and update_date information.
Assuming you want the latest update out of duplicates this one should work:
SELECT id, max(update_date) AS last_update
FROM
( (select id,update_date from table1 where [conditions])
UNION
(select id,update_date from table2 where [conditions]) ) both_tables
GROUP BY id
ORDER by last_update DESC
Wrap the query in a DISTINCT block:
SELECT DISTINCT * FROM (
select id,update_date from table1 where [condition]
UNION
select id,update_date from table2 where [condition]
)
order by update_date desc;
Limit the second query's results:
select id, update_date
from table1
where [conditions]
union
select id, update_date
from table2
where [conditions]
and id not in (select id from table1 where [conditions])

how to order a mysql selection

I'm selecting data from two different tables which have a common field "date" and i want to order by date desc but i can't get it to work and i haven't found much help googleing about it.
SELECT table1.id, table1.date, table2.id, table2.date FROM table1, table2 ORDER BY
Also i would appreciate any links to read more about these types of queries, it would save me from having to ask here for help all the time :D Thanks.
Unless you want a full-blown cartesian product (where you combine every row in table 1 with every row in table 2), you'll need a limiting where clause, something like:
select a.id, b.id, b.date
from table1 a, table2 b
where a.date = b.date
order by b.date desc
The where clause in the above select will only combine rows from the two tables where the dates are identical, which is what it sounds like you need.
If instead, you want to get the ID and date from two different tables and sort by the date, you probably need something like:
select id, date
from table1
union all
select id, date
from table2
order by 2 desc
This will return the IDs and dates from both tables, unioned together, then sort using a column number rather than name.
Something like:
SELECT table1.id, table1.date, table2.id, table2.date FROM table1, table2 ORDER BY table1.date
An introduction to SQL ORDER BY could be found here: http://www.w3schools.com/sql/sql_orderby.asp.
SELECT table1.id, table1.date, table2.id, table2.date FROM table1, table2 ORDER BY table2.date DESC
if you want to order by table2's date
OR
SELECT table1.id, table1.date, table2.id, table2.date FROM table1, table2 ORDER BY table1.date DESC
You could use UNION ALL to combine the table queries, something like this:
SELECT * FROM
(
SELECT 1 AS id, date FROM table1
UNION ALL
SELECT 2 AS id, date FROM table2
) T1
ORDER BY date