mysql union and group by similar fields - mysql

Here is my query (I replaced table names with generic ones). I am trying to do a union all on two different queries in order to group them all by date so that results with similar dates come out as one row.
I am getting the "Every derived table must have its own alias" error when attempting to execute. What am I typing in wrong?
I have researched this but couldn't find the answer. Every selected field has an alias? Or is the issue in the first SELECT?
SELECT SUM(val), id, dat, title FROM (
SELECT table1.product_id as id, SUM(table1.qty) as val, DATE_FORMAT(table1.created, '%Y-%m-1') as dat, table2.title as title
FROM table1
LEFT JOIN table3 ON table1.event_id = table3.id
LEFT JOIN table2 ON table1.product_id = table2.id
WHERE table1.user_id = $user_id AND table3.active != 2 AND table3.temp = 0 AND table2.active != 2
GROUP BY dat
UNION ALL
SELECT table4.product_id as id, SUM(table4.qty) as val, DATE_FORMAT(table4.created, '%Y-%m-1') as dat, table2.title as title
FROM table4
LEFT JOIN table5 ON table4.festival_id = table5.id
LEFT JOIN table2 ON table4.product_id = table2.id
WHERE table4.user_id = $user_id AND table5.active != 2 AND table2.active != 2
GROUP BY dat
)
GROUP BY id
ORDER BY dat ASC
Here is what I am attempting to do:
My original result:
Array
(
[0] => stdClass Object
(
[id] => 1
[val] => 1
[dat] => 2012-05-1
[title] => Test Product
)
[1] => stdClass Object
(
[id] => 1
[val] => 8
[dat] => 2012-06-1
[title] => Test Product
)
[2] => stdClass Object
(
[id] => 2
[val] => 4
[dat] => 2012-06-1
[title] => Test Product 2
)
[3] => stdClass Object
(
[id] => 3
[val] => 6
[dat] => 2012-06-1
[title] => Test Product 3
)
[4] => stdClass Object
(
[id] => 1
[val] => 10
[dat] => 2012-05-1
[title] => Test Product
)
[5] => stdClass Object
(
[id] => 1
[val] => 8
[dat] => 2012-06-1
[title] => Test Product
)
[6] => stdClass Object
(
[id] => 2
[val] => 3
[dat] => 2012-06-1
[title] => Test Product 2
)
[7] => stdClass Object
(
[id] => 3
[val] => 3
[dat] => 2012-06-1
[title] => Test Product 3
)
)
So if they have a similar date and ID, I need those to be just one result. Like so:
Array
(
[0] => stdClass Object
(
[id] => 1
[val] => 11
[dat] => 2012-05-1
[title] => Test Product
)
[1] => stdClass Object
(
[id] => 1
[val] => 8
[dat] => 2012-06-1
[title] => Test Product
)
[2] => stdClass Object
(
[id] => 2
[val] => 7
[dat] => 2012-06-1
[title] => Test Product 2
)
[3] => stdClass Object
(
[id] => 3
[val] => 9
[dat] => 2012-06-1
[title] => Test Product 3
)
)
Please let me know if you need anything else. Thanks in advance.

Try this:
SELECT SUM(val), id, dat, title FROM (
SELECT table1.product_id as id, SUM(table1.qty) as val, DATE_FORMAT(table1.created, '%Y-%m-1') as dat, table2.title as title
FROM table1
LEFT JOIN table3 ON table1.event_id = table3.id
LEFT JOIN table2 ON table1.product_id = table2.id
WHERE table1.user_id = $user_id AND table3.active != 2 AND table3.temp = 0 AND table2.active != 2
GROUP BY dat
UNION ALL
SELECT table4.product_id as id, SUM(table4.qty) as val, DATE_FORMAT(table4.created, '%Y-%m-1') as dat, table2.title as title
FROM table4
LEFT JOIN table5 ON table4.festival_id = table5.id
LEFT JOIN table2 ON table4.product_id = table2.id
WHERE table4.user_id = $user_id AND table5.active != 2 AND table2.active != 2
GROUP BY dat
) AS t
GROUP BY id, dat
ORDER BY dat ASC
As the error suggests, every view/derived table must have an alias..
Edit: This will give you records with distinct id/dat pair. Seems this is what is you are after.

Related

Why Is This Wordpress Query Returning 18 Results Instead of Three

I want to find users whose usernames start with "developer"; however, when I used the query below, I got 18 results when only two should return, based on the number of users in the database. Is there something wrong with the query that is causing this?
SELECT SQL_CALC_FOUND_ROWS wp_users.ID,wp_users.user_login
FROM wp_users
INNER JOIN wp_usermeta
ON ( wp_users.ID = wp_usermeta.user_id )
WHERE wp_users.ID !='1' AND wp_users.user_login LIKE 'developer%' OR (wp_usermeta.meta_key = 'nickname' AND wp_usermeta.meta_value LIKE 'developer%') OR (wp_usermeta.meta_key = 'first_name' AND wp_usermeta.meta_value LIKE 'developer%')
ORDER BY user_login ASC
The actual results:
Array (
[0] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[1] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[2] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[3] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[4] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[5] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[6] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[7] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[8] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[9] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[10] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[11] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[12] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[13] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[14] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[15] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[16] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[17] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
[18] => stdClass Object ( [ID] => 6 [user_login] => developer [id] => 6 )
)
Do all users have wp_usermeta entries for nickname and first_name? If not, you may need to change the join to a LEFT JOIN.
SELECT SQL_CALC_FOUND_ROWS DISTINCT wp_users.ID, wp_users.user_login
FROM wp_users
INNER JOIN wp_usermeta
ON wp_users.ID = wp_usermeta.user_id
AND wp_usermeta.meta_key IN ('nickname', 'first_name')
WHERE wp_users.ID != 1
AND ( wp_users.user_login LIKE 'developer%' OR wp_usermeta.meta_value LIKE 'developer%')
ORDER BY user_login ASC

How to return array while using GROUP BY

Right now, I have this query:
SELECT COUNT(*) AS Count, SUM(Ask) AS Ask, SUM(Cost) AS Cost, Provider, Factura FROM store_items
WHERE (
Provider NOT IN(SELECT Provider FROM store_provider_invoices)
AND Factura NOT IN(SELECT Factura FROM store_provider_invoices)
)
OR Factura NOT IN(SELECT Factura FROM store_provider_invoices)
GROUP BY Provider, Factura
This is working great, and returns the following array:
Array (
[0] => Array (
[Count] => 1
[ID] => 13
[Ask] => 20.00
[Cost] => 10.00
[Provider] => 5
[Factura] => 8
)
[1] => Array (
[Count] => 1
[ID] => 18
[Ask] => 125.01
[Cost] => 110.01
[Provider] => 5
[Factura] => 34
)
[3] => Array (
[Count] => 3
[ID] => 14
[Ask] => 210.00
[Cost] => 150.00
[Provider] => 6
[Factura] => 5
)
)
What I would like to do is to also return all the ID's that match the query from the store_items table, like:
Array (
[0] => Array (
[ID] => Array (
[0] => 101
)
[Count] => 1
[Ask] => 20.00
[Cost] => 10.00
[Provider] => 5
[Factura] => 8
)
[1] => Array (
[ID] => Array (
[0] => 102
)
[Count] => 1
[Ask] => 125.01
[Cost] => 110.01
[Provider] => 5
[Factura] => 34
)
[3] => Array (
[ID] => Array (
[0] => 103
[1] => 104
[2] => 105
)
[Count] => 3
[Ask] => 210.00
[Cost] => 150.00
[Provider] => 6
[Factura] => 5
)
)
So, for instance, in the last array element above, instead of just returning a Count of 3, also return the ID's of each row that it counted.
You can't really get nested results, but you could use
GROUP_CONCAT(DISTINCT store_items.ID ORDER BY ID) AS siIDs
to get a comma-separated list of id values.
You can also modify the separator
http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat

Optimizing an union SQL query

I've got a big query that all contain same types I need for a feed that I list in my app. Now the problem is that this query isn't very fast. I'm thinking that if I limit each individual union it might speed it up a bit but I'm not sure.
So basically my question is how could I optimize this query to execute faster?
SELECT DISTINCT
alert_id,
uniquekey,
type,
user_id,
date_added
FROM
(
( SELECT
r.alert_id,
r.alert_id AS uniquekey,
'reply' AS `type`,
r.user_id,
r.date_added
FROM
`reply` r
LEFT JOIN `alerts` a
ON r.alert_id = a.alert_content_id
WHERE
r.user_id = :id
AND a.hide = '0'
ORDER BY
date_added DESC )
UNION
( SELECT
r.alert_id,
r.alert_id AS uniquekey,
'replyfromfollowing' AS `type`,
r.user_id,
r.date_added
FROM
`reply` r
LEFT JOIN `alerts` a
ON r.alert_id = a.alert_content_id
WHERE
r.user_id IN( '$followingstring' )
AND a.hide = '0'
ORDER BY date_added DESC )
UNION
( SELECT
i.alert_id,
i.alert_id AS uniquekey,
'liked' AS `type`,
i.user_id,
i.date_added
FROM
`interactions` i
LEFT JOIN `alerts` a
ON i.alert_id = a.alert_content_id
WHERE
i.user_id = :id
AND a.hide = '0'
GROUP BY
alert_id
ORDER BY
date_added DESC )
UNION
( SELECT
i.alert_id,
i.alert_id AS uniquekey,
'likedfromfollowing' AS `type`,
i.user_id,
i.date_added
FROM
`interactions` i
LEFT JOIN `alerts` a
ON i.alert_id = a.alert_content_id
WHERE
i.user_id IN ( '$followingstring' )
AND a.hide = '0'
GROUP BY
alert_id
ORDER BY
date_added DESC )
UNION
( SELECT
alerts as alert_id,
alert_content_id AS uniquekey,
'following' AS `type`,
user_id,
date_added
FROM
alerts a
LEFT JOIN `alerts_content` ac
ON ac.id = a.alert_content_id
WHERE
a.user_id IN ( '$followingstring' )
AND ac.anoniem = '0'
AND a.hide = '0'
GROUP BY
alert_id
ORDER BY
date_added DESC )
) joined
GROUP BY
uniquekey
ORDER BY
date_added DESC
LIMIT
".(int)$start.",20"
table structures
Reply table Structure:
id
user_id
alert_id
description
reply_on_alert
reply_on_reply
date_added
Interaction table Structure:
id
alert_id
action_id
reply_id
user_id
date_added
Alerts table structure(Yes i know BIG mistake naming `id` : `alerts`):
alerts
title
alert_content_id
user_id
cat
lat
lon
state
hide
date_added
alerts_content table structure:
id
alert_id
description
img
results of query:
Array
(
[0] => Array
(
[alert_id] => 173404
[uniquekey] => 173404
[type] => reply
[user_id] => 2
[date_added] => 2015-06-01 16:34:16
)
[1] => Array
(
[alert_id] => 172174
[uniquekey] => 172174
[type] => replyfromfollowing
[user_id] => 1380
[date_added] => 2015-06-01 16:01:04
)
[2] => Array
(
[alert_id] => 171772
[uniquekey] => 171772
[type] => liked
[user_id] => 2
[date_added] => 2015-06-01 15:58:44
)
[3] => Array
(
[alert_id] => 149423
[uniquekey] => 149423
[type] => reply
[user_id] => 2
[date_added] => 2015-06-01 15:25:56
)
[4] => Array
(
[alert_id] => 164742
[uniquekey] => 164742
[type] => reply
[user_id] => 2
[date_added] => 2015-05-12 09:46:39
)
[5] => Array
(
[alert_id] => 163344
[uniquekey] => 163344
[type] => replyfromfollowing
[user_id] => 3
[date_added] => 2015-05-12 09:44:46
)
[6] => Array
(
[alert_id] => 164205
[uniquekey] => 164205
[type] => liked
[user_id] => 2
[date_added] => 2015-05-11 11:06:39
)
[7] => Array
(
[alert_id] => 160890
[uniquekey] => 160890
[type] => replyfromfollowing
[user_id] => 1380
[date_added] => 2015-05-08 14:29:34
)
[8] => Array
(
[alert_id] => 163002
[uniquekey] => 163002
[type] => replyfromfollowing
[user_id] => 1380
[date_added] => 2015-05-08 13:31:12
)
[9] => Array
(
[alert_id] => 159123
[uniquekey] => 159123
[type] => replyfromfollowing
[user_id] => 48
[date_added] => 2015-04-30 15:10:32
)
[10] => Array
(
[alert_id] => 150546
[uniquekey] => 150546
[type] => replyfromfollowing
[user_id] => 16
[date_added] => 2015-04-21 21:52:49
)
[11] => Array
(
[alert_id] => 149497
[uniquekey] => 149497
[type] => reply
[user_id] => 2
[date_added] => 2015-04-10 15:19:06
)
[12] => Array
(
[alert_id] => 141078
[uniquekey] => 141078
[type] => liked
[user_id] => 2
[date_added] => 2015-04-10 15:15:32
)
[13] => Array
(
[alert_id] => 125466
[uniquekey] => 125466
[type] => replyfromfollowing
[user_id] => 3
[date_added] => 2015-04-09 00:15:22
)
[14] => Array
(
[alert_id] => 134592
[uniquekey] => 134592
[type] => replyfromfollowing
[user_id] => 3
[date_added] => 2015-04-09 00:11:04
)
[15] => Array
(
[alert_id] => 124194
[uniquekey] => 124194
[type] => likedfromfollowing
[user_id] => 3
[date_added] => 2015-04-09 00:08:35
)
[16] => Array
(
[alert_id] => 128645
[uniquekey] => 128645
[type] => likedfromfollowing
[user_id] => 3
[date_added] => 2015-04-09 00:07:29
)
[17] => Array
(
[alert_id] => 144867
[uniquekey] => 144867
[type] => replyfromfollowing
[user_id] => 3
[date_added] => 2015-04-06 13:59:19
)
[18] => Array
(
[alert_id] => 133355
[uniquekey] => 133355
[type] => liked
[user_id] => 2
[date_added] => 2015-03-31 16:16:15
)
[19] => Array
(
[alert_id] => 141075
[uniquekey] => 141075
[type] => liked
[user_id] => 2
[date_added] => 2015-03-30 15:17:01
)
)
Some possibilities, in no particular order:
Optimization #1:
Use LIMIT in the subqueries, too. However, since you are using OFFSET, it may not be obvious how to do it.
Before the query, calculate $start+20 and put it into, say, $limit. Then use LIMIT $limit for the inner queries. No, don't use an OFFSET on them. This guarantees that you get enough rows from each query to satisfy the outer OFFSET $start LIMIT 20.
Optimization #2:
Restructure the tables so that you don't need to JOIN to another table (alerts) to find out whether to show the record. That is, having hide prevents a number of potential optimizations. Before advising further, we need to understand the need for LEFT. Are there rows in reply, etc, that are not in alerts? If not, get rid of the LEFT and look into searching alerts with theOFFSETandLIMIT`, then joining to the 4 other tables.
Optimization #3:
Restructure the data so that there is one core table, with alerts and the 4 other tables hanging off it. Be sure to have most (all?) of the fields needed for this query in this new table.
Optimization #4:
The current structure requires the full scan of each of the 4 tables before even thinking about OFFSET and LIMIT. This smells like "pagination"; is it? For optimizing "pagination", the goals are to avoid the table scan and OFFSET; instead remember where you "left off" so that the query can be
WHERE ... AND x < $left_off
ORDER by x DESC
LIMIT 20
This should make it possible to read only 20 rows, not the entire table(s). That would make the query much faster, especially for later pages. (A bigger OFFSET costs more time`)
I discuss pagination optimization in my blog.

Altering a query to consolidate answers in a poll

I have the following mysql query:
SELECT p.id, p.title, p.description, a.id, a.answer, q.id, q.question
FROM x_trybe_poll_relation pr
LEFT JOIN x_polls p
ON pr.poll_id = p.id
LEFT JOIN x_polls_question_relation qr
ON p.id = qr.poll_id
LEFT JOIN x_polls_questions q
ON qr.question_id = q.id
LEFT JOIN x_polls_answers a
ON q.id = a.question_id
WHERE pr.trybe_id = '%s'
Which returns:
[polls] => Array
(
[0] => Array
(
[id] => 79de13af1978ab14f56b4305956b2d93cd42e0fb
[title] => Poll 1
[description] => Poll 1 Description
[answer] => Danny Welbeck
[question] => Who is the best player in the Arsenal squad?
)
[1] => Array
(
[id] => 79de13af1978ab14f56b4305956b2d93cd42e0fb
[title] => Poll 1
[description] => Poll 1 Description
[answer] => Alexis Sanchez
[question] => Who is the best player in the Arsenal squad?
)
)
How do I adjust the mysql query to get the following:
[polls] => Array
(
[0] => Array
(
[id] => 79de13af1978ab14f56b4305956b2d93cd42e0fb
[title] => Poll 1
[description] => Poll 1 Description
[answers] => Array (
[0] => Array (
[id] => abc
[answer] => Danny Welbeck
)
[1] => Array (
[id] => def
[answer] => Alexis Sanchez
)
)
[question] => Who is the best player in the Arsenal squad?
)
)
I want to get the poll question, and get the array of pre-generated answers with one query.
Is this possible, or should I just run two queries?
Thanks

Mysql Count 1 by 1

$sql=sprintf("SELECT * FROM stitch);
This my array.
[stitch] => Array
(
[0] => Array
(
[id] => 7,
[name] => Sew buttonhole to front fly
)
[1] => Array
(
[id] => 8,
[name] => Sleeve hem
)
)
)
I need this result
[stitch] => Array
(
[0] => Array
(
[id] => 7,
[name] => Sew buttonhole to front fly
[number_stitch] => 1
)
[1] => Array
(
[id] => 8,
[name] => Sleeve hem
[number_stitch] => 2
)
)
)
how i do these [number_stitch] ?
Try
select s.*, #rowcount:=#rowcount+1 ‘number_stitch’ from stitch s, (SELECT #rowcount:=0) r order by id;