Selecting records from multiple tables with counts - php

I have seen many similar posts but cannot seem to pair similar cases to my exact solution/needs.
I have data in 6 tables, and need to get a list of all cities from each table and the amount of records for each city along with it.
My current query:
(SELECT res.CITY FROM rets_property_res res)
UNION ALL
(SELECT rnt.CITY FROM rets_property_rnt rnt)
UNION ALL
(SELECT lnd.CITY FROM rets_property_lnd lnd)
UNION ALL
(SELECT hir.CITY FROM rets_property_hir hir)
UNION ALL
(SELECT cnd.CITY FROM rets_property_cnd cnd)
UNION ALL
(SELECT mul.CITY FROM rets_property_mul mul)
ORDER BY CITY ASC
I have tried many efforts to add the count but cannot get the syntax correct as I am not so great with mySql syntax.

(i). When you need the count of rows based on a filed or fields you can use Group by on that field(s).
Now you want to know count of each table so you need a field that specify table names like tName and ...
With this you will have count of cities of each table
SELECT count(*) AS CNT, CITY, tName
FROM (
SELECT res.CITY ,'res' as tName
FROM rets_property_res res
UNION ALL
SELECT rnt.CITY,'rnt' as tName
FROM rets_property_rnt rnt
UNION ALL
SELECT lnd.CITY,'lnd' as tName
FROM rets_property_lnd lnd
UNION ALL
SELECT hir.CITY,'hir' as tName
FROM rets_property_hir hir
UNION ALL
SELECT cnd.CITY,'cnd' as tName
FROM rets_property_cnd cnd
UNION ALL
SELECT mul.CITY,'mul' as tName
FROM rets_property_mul mul
) as DT
Group by tName, CITY
ORDER BY CITY ASC

If you put your whole query in a sub-query then you can calculate your COUNT() off those results:
SELECT CITY, COUNT(*)
FROM (
(SELECT res.CITY FROM rets_property_res res)
UNION ALL
(SELECT rnt.CITY FROM rets_property_rnt rnt)
UNION ALL
(SELECT lnd.CITY FROM rets_property_lnd lnd)
UNION ALL
(SELECT hir.CITY FROM rets_property_hir hir)
UNION ALL
(SELECT cnd.CITY FROM rets_property_cnd cnd)
UNION ALL
(SELECT mul.CITY FROM rets_property_mul mul)
)
GROUP BY CITY

Try this, it will give you the count of each city from each table
(SELECT res.CITY, resDup.res_count FROM rets_property_res res
JOIN (SELECT COUNT(CITY) res_count FROM rets_property_res GROUP BY CITY) resDup ON `resDup`.`CITY` = `res`.`CITY`
)
UNION ALL
(SELECT rnt.CITY, rntDup.rnt_count FROM rets_property_rnt rnt
JOIN (SELECT COUNT(CITY) rnt_count FROM rets_property_rnt GROUP BY CITY) rntDup ON `rntDup`.`CITY` = `rnt`.`CITY`
)
UNION ALL
(SELECT lnd.CITY, lndDup.lnd_count FROM rets_property_lnd lnd
JOIN (SELECT COUNT(CITY) lnd_count FROM rets_property_lnd GROUP BY CITY) lndDup ON `lndDup`.`CITY` = `lnd`.`CITY`
)
UNION ALL
(SELECT hir.CITY, hirDup.hir_count FROM rets_property_hir hir
JOIN (SELECT COUNT(CITY) hir_count FROM rets_property_hir GROUP BY CITY) hirDup ON `hirDup`.`CITY` = `hir`.`CITY`
)
UNION ALL
(SELECT cnd.CITY, cndDup.cnd_count FROM rets_property_cnd cnd
JOIN (SELECT COUNT(CITY) cnd_count FROM rets_property_cnd GROUP BY CITY) cndDup ON `cndDup`.`CITY` = `cnd`.`CITY`
)
UNION ALL
(SELECT mul.CITY, mulDup.mul_count FROM rets_property_mul mul
JOIN (SELECT COUNT(CITY) mul_count FROM rets_property_mul GROUP BY CITY) mulDup ON `mulDup`.`CITY` = `mul`.`CITY`
)
ORDER BY CITY ASC
Let me know if there is any issue

Related

multiple sum from different tables [duplicate]

I have a union of three tables (t1, t2, t3).
Each rerun exactly the same number of records, first column is id, second amount:
1 10
2 20
3 20
1 30
2 30
3 10
1 20
2 40
3 50
Is there a simple way in SQL to sum it up, i.e. to only get:
1 60
2 80
3 80
select id, sum(amount) from (
select id,amount from table_1 union all
select id,amount from table_2 union all
select id,amount from table_3
) x group by id
SELECT id, SUM(amount) FROM
(
SELECT id, SUM(amount) AS `amount` FROM t1 GROUP BY id
UNION ALL
SELECT id, SUM(amount) AS `amount` FROM t2 GROUP BY id
) `x`
GROUP BY `id`
I groupped each table and unioned because i think it might be faster, but you should try both solutions.
Subquery:
SELECT id, SUM(amount)
FROM ( SELECT * FROM t1
UNION ALL SELECT * FROM t2
UNION ALL SELECT * FROM t3
)
GROUP BY id
Not sure if MySQL uses common table expression but I would do this in postgres:
WITH total AS(
SELECT id,amount AS amount FROM table_1 UNION ALL
SELECT id,amount AS amount FROM table_2 UNION ALL
SELECT id,amount AS amount FROM table_3
)
SELECT id, sum(amount)
FROM total
I think that should do the trick as well.
As it's not very clear from previous answers, remember to give aliases (on MySQL/MariaDb) or you'll get error:
Every derived table must have its own alias
select id, sum(amount) from (
select id,amount from table_1 union all
select id,amount from table_2 union all
select id,amount from table_3
) AS 'aliasWhichIsNeeded'
group by id
Yes!!! Its okay! Thanks!!!!
My code finishing:
SELECT SUM(total)
FROM (
(SELECT 1 as id, SUM(e.valor) AS total FROM entrada AS e)
UNION
(SELECT 1 as id, SUM(d.valor) AS total FROM despesa AS d)
UNION
(SELECT 1 as id, SUM(r.valor) AS total FROM recibo AS r WHERE r.status = 'Pago')
) x group by id
SELECT BANKEMPNAME, workStation, SUM (CALCULATEDAMOUNT) FROM(
SELECT BANKEMPNAME, workStation, SUM(CALCULATEDAMOUNT) AS CALCULATEDAMOUNT,SALARYMONTH
FROM dbo.vw_salaryStatement
WHERE (ITEMCODE LIKE 'A%')
GROUP BY BANKEMPNAME,workStation, SALARYMONTH
union all
SELECT BANKEMPNAME, workStation, SUM(CALCULATEDAMOUNT) AS CALCULATEDAMOUNT,SALARYMONTH
FROM dbo.vw_salaryStatement
WHERE (ITEMCODE NOT LIKE 'A%')
GROUP BY BANKEMPNAME, workStation, SALARYMONTH) as t1
WHERE SALARYMONTH BETWEEN '20220101' AND '20220131'
group by BANKEMPNAME, workStation
order by BANKEMPNAME asc
IN MSSQL You can write this way, But Doing UNION ALL THE Column should be the same for both ways.
I have given this example So that you can understand the process...

Getting min value of two MySQL tables

I've got stuck at joining two tables and fetching the min value of a price.
I have two tables "tb1" and "tb2".
Both includes ean, price and some other columns.
I wan't to get the cheapest price for same ean's.
So I got this left join:
SELECT price,* FROM tb1 as w left join tb2 as e on w.ean=e.ean
But how do I get the cheapest price?
I know MIN() but the problem is, the min price could be in tb1 or tb2...
Hope you could help me :)
Regards :)
You can use the following solution using a sub-select with UNION ALL to merge the tables into one (tbAll):
SELECT ean, MIN(price) FROM (
SELECT ean, price FROM tb1
UNION ALL
SELECT ean, price FROM tb2
) tbAll
GROUP BY ean
... or another solution using the LEFT JOIN:
SELECT w.ean, MIN(LEAST(w.price, e.price))
FROM tb1 AS w LEFT JOIN tb2 AS e ON w.ean = e.ean
GROUP BY w.ean
In case you need additional information, you can use the UNION ALL solution with additional ROW_NUMBER (available since MySQL 8.0):
SELECT t.ean, t.price, t.merchant FROM (
SELECT ean, price, merchant, ROW_NUMBER() OVER (PARTITION BY ean ORDER BY ean, price) AS rn
FROM (
SELECT ean, price, merchant FROM tb1
UNION ALL
SELECT ean, price, merchant FROM tb2
) tbAll
)t WHERE t.rn = 1
... or in case you are using a MySQL version earlier 8.0 you can use the following:
SELECT t.ean, t.price, t.merchant FROM (
SELECT ean, price, merchant, IF(#prev <> ean, #rn:=0, #rn), #prev:=ean, #rn:=#rn+1 AS rn
FROM (
SELECT ean, price, merchant FROM tb1
UNION ALL
SELECT ean, price, merchant FROM tb2
ORDER BY ean, price
) tbAll JOIN (SELECT #rn:=0) init_rn JOIN (SELECT #prev:='') init_prev
)t WHERE t.rn = 1
demo on dbfiddle.uk
Use Case
CASE
WHEN w.price < e.price THEN w.price
ELSE e.price
END AS MINPRICE

UNION ALL - return from which table the result is

I have this code running (Thanks to #Gordon Linoff).
SELECT alid, max(ts) as ts
FROM ((SELECT AL.alID, AL.al_date AS ts FROM AL)
UNION ALL
(SELECT MRA.mraNR, MRA.add_date FROM MRA)
UNION ALL
(SELECT AMG.mraNR, AMG.lastupd FROM AMG)
) t
GROUP BY alID
ORDER BY ts DESC
LIMIT 20;
Now we need to have a third value, knowing from which table the result comes (AL, MRA or AMG).
Already tried options like this, but nothing seems to work.
SELECT alid, TABLEVALUEWENEED as RES, max(ts) as ts
FROM ((SELECT AL.alID, TABLEVALUEWENEED AS RES1, AL.al_date AS ts FROM AL)
UNION ALL
(SELECT MRA.mraNR, TABLEVALUEWENEED AS RES2, MRA.add_date FROM MRA)
UNION ALL
(SELECT AMG.mraNR, TABLEVALUEWENEED AS RES3, AMG.lastupd FROM AMG)
) t
GROUP BY alID
ORDER BY ts DESC
LIMIT 20;
And, to get those tables values as php output like:
$RES1=$rows["RES1"];
Any help is appreciated!
Just put the string with the table name instead of TABLEVALUEWENEED:
SELECT alid, RES1, max(ts) as ts
FROM ((SELECT AL.alID, 'AL' AS RES1, AL.al_date AS ts FROM AL)
UNION ALL
(SELECT MRA.mraNR, 'MRA' AS RES1, MRA.add_date FROM MRA)
UNION ALL
(SELECT AMG.mraNR, 'AMG' AS RES1, AMG.lastupd FROM AMG)
) t
GROUP BY alID
ORDER BY ts DESC
LIMIT 20;
I also assume you wanted the alias to always be 'RES1' not 'RES1', 'RES2', 'RES3', because the name of the column will be the alias from the first SELECT of the UNION anyway.

Union multiple table with different column for order by date

I search a solution for do this req' SQL because this don't work, like_supplier table and like product table work correctly but when i add the table comments this don't work, i know haven't the same column in table comment but how i can do this correctly ? Thanks in advance.
SELECT DISTINCT *
FROM (
(SELECT DISTINCT lp.customer_id, lp.`date`, lp.`product_id`, lp.`classes`, Null as `comment`
FROM
`like_product` as lp,
`supplier_products` as sp
WHERE
sp.`product_id` = lp.`product_id`
AND sp.`supplier_id`=".$customer_id.")
UNION DISTINCT
(SELECT DISTINCT ls.`customer_id`,ls.`date`, Null as `product_id`, ls.`classes`, Null as `comment`
FROM
`like_supplier` as ls,
`supplier_products` as sp
WHERE
sp.`supplier_id`=".$customer_id."
AND sp.`product_id` = ls.`product_id`)
UNION DISTINCT
(SELECT com.`sender_id`, com.`date`, com.`product_id`, com.`classes`, com.`comment`
FROM `comments` as com)) as a
ORDER BY a.`date` desc
Try just to clarify all aliases and column names:
SELECT DISTINCT
a.id,
a.`date`,
a.product_id,
a.classes,
a.comment
FROM (
(SELECT DISTINCT
lp.customer_id as id,
lp.`date` as `date`,
lp.`product_id` as product_id,
lp.`classes` as classes,
Null as comment
FROM
`like_product` as lp
INNER JOIN
(SELECT *
FROM
`supplier_products`
WHERE
supplier_id=".$customer_id."
) as sp
ON
sp.`product_id` = lp.`product_id`
)
UNION DISTINCT
(SELECT DISTINCT
ls.`customer_id` as id,
ls.`date` as `date`,
Null as `product_id`,
ls.`classes`,
Null as `comment`
FROM
`like_supplier` as ls
INNER JOIN
(SELECT
*
FROM
`supplier_products`
WHERE
supplier_id=".$customer_id."
) as sp
ON sp.`product_id` = ls.`product_id`)
UNION DISTINCT
(SELECT
com.`sender_id` as id,
com.`date` as `date`,
com.`product_id` as product_id,
com.`classes` as classes,
com.`comment` as comment
FROM `comments` as com
)
) as a
ORDER BY a.`date` desc

Union query to fetch SUM values

Totally 12 db tables(some tables repeated). I have to fetch SUM(values) from each table of particular date.I have used UNION query,But it returns the value of first table used in query.
Remaining table returned nothing.Can Anybody help me.Here my code.
$sel = mysql_query("
SELECT
SUM(collection_amount) AS cash_total
FROM
collection_entry
WHERE
date='$entered_date'
AND collection_type='DC'
UNION
SELECT
SUM(amt) AS cheque_redeposit_total
FROM
cheque_redeposit
WHERE
redeposited_on1
OR redeposited_on2='$entered_date'
UNION
SELECT
SUM(collection_amount) AS not_cleared_total
FROM
collection_entry
WHERE
cheque_status='not cleared'
AND date='$entered_date'
UNION
SELECT
SUM(collection_amt) AS route_collection_total
FROM
route_collection
WHERE
entered_date='$entered_date'
UNION
SELECT
SUM(amt) AS return_total
FROM
cheque_return
WHERE
return_date1 OR return_date2 OR return_date3='$entered_date'
UNION
SELECT
SUM(collection_amount) AS cheque_total
FROM
collection_entry
WHERE
collection_type='CC'
AND date='$entered_date'
UNION
SELECT
SUM(debit2) AS voucher_receipt_total
FROM
voucher_posting
WHERE
receipt_type='R'
AND date='$entered_date'
UNION
SELECT
SUM(credit2) AS voucher_payment_total
FROM
voucher_posting
WHERE
receipt_type='P'
AND date='$entered_date'
UNION
SELECT
SUM(amt) AS others_total
FROM
others_remittance
WHERE
entered_date='$entered_date'
UNION
SELECT
SUM(amt) AS short_total
FROM
short_remittance
WHERE
entered_date='$entered_date'
UNION
SELECT
SUM(amount) AS more_paid
FROM
difference
WHERE
entered_date='$entered_date'
and paid_type='more'
UNION
SELECT
SUM(amount) AS unpaid
FROM
difference
WHERE
entered_date='$entered_date'
and paid_type='unpaid'");
while($row=mysql_fetch_array($sel))
{
$cash_total=$row['cash_total'];
$cheque_redeposit_total=$row['cheque_redeposit_total'];
$not_cleared_total=$row['not_cleared_total'];
$route_collection_total=$row['route_collection_total'];
$return_total=$row['return_total'];
$cheque_total=$row['cheque_total'];
$voucher_receipt_total=$row['voucher_receipt_total'];
$voucher_payment_total=$row['voucher_payment_total'];
$others_total=$row['others_total'];
$short_total=$row['short_total'];
$more_paid=$row['more_paid'];
$unpaid=$row['unpaid'];
$net_total = (($cash_total + $route_collection_total) - $return_total);
}
UNION just appends rows to one another. So in your case you just get a list of your sums in a row-wise fashion.
[value for cash_total]
[value for cheque_redeposit_total]
[value for not_cleared_total]
...
If you really have to get all the data in one row, you can use something like this:
SELECT * FROM
(SELECT SUM(collection_amount) AS cash_total FROM collection_entry WHERE date='$entered_date' AND collection_type='DC') as t1,
(SELECT SUM(amt) AS cheque_redeposit_total FROM cheque_redeposit WHERE redeposited_on1 OR redeposited_on2='$entered_date') AS t2,
(SELECT SUM(collection_amount) AS not_cleared_total FROM collection_entry WHERE cheque_status='not cleared' AND date='$entered_date') AS t3,
(SELECT SUM(collection_amt) AS route_collection_total FROM route_collection WHERE entered_date='$entered_date') AS t4,
...

Categories