Union multiple table with different column for order by date - php

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

Related

MYSQL unable to load OR operator on different tables

I think nothing wrong with my query, but don't know why system becomes very slow when I load this code in phpmyadmin. Any advice please help.
select
*
from
`table1`
left join
`table2`
on
table1.id = table2.id
where
(
(table1.email = 'test#test.com' and table1.mobile = '99999999')
or
(table2.email = 'test#test.com' and table2.mobile = '99999999')
)
Thanks in advance.
Add this to each table:
INDEX(email, mobile) -- in either order.
If that does not speed it up enough, then also turn the OR into a UNION:
SELECT *
FROM ( ( SELECT id FROM table1 WHERE email = ... AND mobile = ... )
UNION DISTINCT
( SELECT id FROM table2 WHERE email = ... AND mobile = ... )
) AS x
JOIN table1 WHERE table1.id = x.id
JOIN table2 WHERE table2.id = x.id
Add these indexes:
ALTER TABLE `table1` ADD INDEX `table1_idx_id` (`id`);
ALTER TABLE `table2` ADD INDEX `table2_idx_id` (`id`);
ALTER TABLE `table1` ADD INDEX `table1_idx_email_mobile_id` (`email`, `mobile`, `id`);
ALTER TABLE `table2` ADD INDEX `table2_idx_email_mobile_id` (`email`, `mobile`, `id`);
And the transformed query (avoiding the OR condition, which is not indexable, by using UNION DISTINCT):
(SELECT
*
FROM
`table1`
LEFT JOIN
`table2` ON table1.id = table2.id
WHERE
((table2.email = 'test#test.com'
AND table2.mobile = '99999999'))) UNION DISTINCT (SELECT
*
FROM
`table1`
LEFT JOIN
`table2` ON table1.id = table2.id
WHERE
((table1.email = 'test#test.com'
AND table1.mobile = '99999999')))
P.S, if there is no option to have duplicates, use UNION ALL instead of UNION DISTINCT, as it should perform better (avoid the duplicates elimination, which can take time).

Reviews Count for each user [duplicate]

I have a SQL statement which requests data from the database.
SELECT `ID`, `To`, `Poster`, `Content`, `Time`, ifnull(`Aura`,0) as `Aura` FROM (
SELECT * FROM (
SELECT DISTINCT * FROM messages m
INNER JOIN
(
SELECT Friend2 as Friend FROM friends WHERE Friend1 = '1'
UNION ALL
SELECT Friend1 as Friend FROM friends WHERE Friend2 = '1'
) friends ON m.Poster = friends.`Friend`
UNION ALL SELECT DISTINCT *, '1' FROM messages where `Poster`='1'
) var
LEFT JOIN
(
select `ID` as `AuraID`, `Status` as `AuraStatus`, count(*) as `Aura`
from messages_aura
) aura ON (var.Poster = aura.AuraID AND var.ID = aura.AuraStatus)
) final
GROUP BY `ID`, `Poster`
ORDER BY `Time` DESC LIMIT 10
Here is my messages_aura table layout. It shows ID, Status and UserID.
Here is the output from the above statement.
(The ID from the above screenshot refers to Poster below and the Status from the above screenshot refers to ID below)
The statement should give the bottom row a Aura count of 1 and the top row an Aura count of 2. What's wrong?
You're missing GROUP BY, so it's counting everything instead of grouping by some columns.
LEFT JOIN
(
select `ID` as `AuraID`, `Status` as `AuraStatus`, count(*) as `Aura`
from messages_aura
GROUP BY AuraID, AuraStatus
) aura ON (var.Poster = aura.AuraID AND var.ID = aura.AuraStatus)

how to convert query sentences to DB::raw eloquent laravel?

SELECT u.*,(
SELECT COUNT(*) FROM (
SELECT id,author_id FROM posts p
UNION ALL
SELECT id, author_id FROM updates up
) total_table WHERE author_id = u.id) as total_post FROM users u ORDER BY total_post
i have query line want to DB::raw. Can you help me??? many thanks
Use raw query like:
DB::select(DB::raw('SELECT u.*,(
SELECT COUNT(*) FROM (
SELECT id,author_id FROM posts p
UNION ALL
SELECT id, author_id FROM updates up
) total_table WHERE author_id = u.id) as total_post FROM users u ORDER BY total_post'));
Reference
Or you can do this by using DB::satement
$query='SELECT u.*,(SELECT COUNT(*) FROM (
SELECT id,author_id FROM posts p
UNION ALL
SELECT id, author_id FROM updates up) total_table WHERE author_id = u.id) as total_post FROM users u ORDER BY total_post';
$data=DB::statement($query);
Like this.

Selecting records from multiple tables with counts

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

Where condition not working with IN Clause

I have a query. In this query I am using a sub query to get the data from the same table with different condition and in the main query I am mentioning the ids that are used to get data in the sub query and putting a condition that the values that are being considered in the main query with the ids should not be empty. If I use a single ID with IN clause in the main query, my query works fine but if I use multiple ids in the main query and add the clause that the values should not be empty, the query does not give me the desired result.Here is my query
SELECT e.id AS `Personal Number`,
e.date AS `Date`,
CONCAT(ep.firstname,' ',ep.lastname) AS `Employee Name`,
IF(ep.sex='M','Male','Female') AS sex,
DATE_FORMAT(p.birthdate,'%m/%d/%Y')AS birthdate,
(SELECT `value` FROM employee_data WHERE history=87 AND DATE=e.date) AS `A`,
(SELECT `value` FROM employee_data WHERE history=603 AND DATE=e.date) AS `B`,
(SELECT `value` FROM employee_data WHERE history=82 AND DATE=e.date) AS `C`,
(SELECT `value` FROM employee_data WHERE history=86 AND DATE=e.date) AS `D`
FROM tbl e
INNER JOIN employee ep ON e.id = ep.id
INNER JOIN tbl2 ap ON ap.date=e.date
INNER JOIN employee_data AS phd ON e.date = phd.date
WHERE (phd.history IN(82,87,603,86) AND phd.value!='') AND ap.date BETWEEN '2013-01-01' AND '2013-09-01'AND e.status!='cancelled'.
I am out of ideas that what to do with this query. Can anyone help. Thanks in advance
Since you fetch values with filter in select clause, do a group by and get max() value in select clause.
max (SELECT `value` FROM employee_data WHERE history=87 AND DATE=e.date) AS `A`,
max (SELECT `value` FROM employee_data WHERE history=603 AND encounter_nr=e.encounter_nr) AS `B`,
max (SELECT `value` FROM employee_data WHERE history=82 AND encounter_nr=e.encounter_nr) AS `C`,
max (SELECT `value` FROM employee_data WHERE history=86 AND encounter_nr=e.encounter_nr) AS `D`
FROM
Here is your problem. Your query is producing four rows when you have the where clause. But, I suspect that you are just expecting one row, or at least, just one row per id.
I think this is the query that you want:
SELECT e.id AS `Personal Number`, e.date AS `Date`,
CONCAT(ep.firstname,' ',ep.lastname) AS `Employee Name`,
IF(ep.sex='M','Male','Female') AS sex,
DATE_FORMAT(p.birthdate,'%m/%d/%Y') AS birthdate,
max(case when history = 87 then value end) as A,
max(case when history = 603 then value end) as B,
max(case when history = 82 then value end) as C,
max(case when history = 86 then value end) as D
FROM tbl e INNER JOIN
employee ep
ON e.id = ep.id INNER JOIN
tbl2 ap ON ap.date = e.date INNER JOIN
employee_data phd
ON e.date = phd.date
WHERE phd.history IN (82, 87, 603, 86) AND phd.value <> '' AND
ap.date BETWEEN '2013-01-01' AND '2013-09-01' AND
e.status <> 'cancelled'
group by e.id;
This should return one row for each employee.
EDIT:
It occurs to me that you might not want an aggregation. You can follow your original approach by removing the join to employee_data in the outer query:
SELECT e.id AS `Personal Number`, e.date AS `Date`,
CONCAT(ep.firstname,' ',ep.lastname) AS `Employee Name`,
IF(ep.sex='M','Male','Female') AS sex,
DATE_FORMAT(p.birthdate,'%m/%d/%Y') AS birthdate,
(SELECT `value` FROM employee_data WHERE history=87 AND DATE=e.date) AS `A`,
(SELECT `value` FROM employee_data WHERE history=603 AND DATE=e.date) AS `B`,
(SELECT `value` FROM employee_data WHERE history=82 AND DATE=e.date) AS `C`,
(SELECT `value` FROM employee_data WHERE history=86 AND DATE=e.date) AS `D`
FROM tbl e INNER JOIN
employee ep
ON e.id = ep.id INNER JOIN
tbl2 ap ON ap.date = e.date
WHERE ap.date BETWEEN '2013-01-01' AND '2013-09-01'AND e.status <> 'cancelled'
HAVING A <> '' and B <> '' and C <> '' and D <> '';
The having clause is a MySQL trick that lets you refer to column aliases in the from clause. It does not imply aggregation in this case.
You would do this if you had an index employee_data(history, date).

Categories