The result I receive:
id sku name GROUP_CONCAT(quantity_received) GROUP_CONCAT(item_cost)
4 00004 Antibacterial Wipes 50,14,25,309,50,14,25,309,50,14,25,309,50,14,25,309,50,14,25,309,50,14,25,309,50,14,25,309,50,14,25,309,50,14,25,309 3.29,3.29,3.29,3.49,3.29,3.29,3.29,3.49,3.29,3.29,3.29,3.49,3.29,3.29,3.29,3.49,3.29,3.29,3.29,3.49,3.29,3.29,3.29,3.49,3.29,3.29,3.29,3.49,3.29,3.29,3.29,3.49,3.29,3.29,3.29,3.49
The result I want:
id sku name GROUP_CONCAT(DISTINCT quantity_received) GROUP_CONCAT(DISTINCT item_cost)
4 00004 Antibacterial Wipes 50,14,25,309 3.29,3.49
The way I resolved this issue was placing DISTINCT in the quantity_recieved select. The problem is that if the quantity has two values that are the same such as 50, 50, 14, 25. The result will be 50, 14, 25. I just want to get rid of the repeating numbers and only get the values once.
Here is the query:
SELECT `product`.`id`,`product`.`sku`,`product`.`name`,
case when coalesce(stock1.`quantity`, '') = ''
then '0'
else stock1.`quantity`
end as qty_warehouse,
case when coalesce(sum(distinct stock2.`quantity`), '') = ''
then '0'
else sum(distinct stock2.`quantity`)
end as qty_events,
case when coalesce(stock1.`quantity`, '') = ''
then '0'
else stock1.`quantity`
end +
case when coalesce(sum(distinct stock2.`quantity`), '') = ''
then '0'
else sum(distinct stock2.`quantity`)
end as qty_total
GROUP_CONCAT(DISTINCT quantity_received) ,
GROUP_CONCAT(DISTINCT item_cost)
FROM (`product`)
LEFT JOIN`shipping_event`
ON `shipping_event`.`product_id` = `product`.`id`
LEFT JOIN `product_stock` as stock1
ON `product`.`id` = `stock1`.`product_id` and `stock1`.`location_id` = 112
LEFT JOIN `product_stock` as stock2
ON `product`.`id` = `stock2`.`product_id` and `stock2`.`location_id` != 112
LEFT JOIN `shipping_list`
ON `shipping_event`.`shipping_list_id` = `shipping_list`.`id`
WHERE `shipping_list`.`type` = 'incoming'
AND `shipping_event`.`end_date` > '2004-01-01 01:01:01'
GROUP BY `product`.`id`
ORDER BY `sku` asc LIMIT 20
I am using group concat just to display the result in this case. I actually sum the quantity_received and then multiple them by the item cost.
You could make a subquery with a GROUP BY and then JOIN to the product table.
The same logic can be applied to the other joined tables as well. If you do that, you can skip the GROUP BY product.id:
SELECT p.id
, p.sku
, p.name
, COALESCE(stock1.quantity, 0) --- minor improvements on
AS qty_warehouse --- the long CASE clauses
, COALESCE(SUM(DISTINCT stock2.quantity), 0)
AS qty_events
, COALESCE(stock1.quantity, 0) + COALESCE(SUM(DISTINCT stock2.quantity), 0)
AS qty_total
, grp.all_quantities_received
, grp.all_item_costs
FROM product AS p
LEFT JOIN
( SELECT product_id
, GROUP_CONCAT(se.quantity_received) AS all_quantities_received
, GROUP_CONCAT(se.item_cost) AS all_item_costs
FROM shipping_event AS se
LEFT JOIN shipping_list AS sl
ON se.shipping_list_id = sl.id
WHERE sl.type = 'incoming'
AND se.end_date > '2004-01-01 01:01:01'
GROUP BY se.product_id
) AS grp
ON grp.product_id = p.id
LEFT JOIN `product_stock` AS stock1
ON p.id = stock1.product_id
AND stock1.location_id = 112
LEFT JOIN product_stock AS stock2
ON p.id = stock2.product_id
AND stock2.location_id <> 112
GROUP BY p.id
ORDER BY sku ASC
LIMIT 20
Related
I have this query that is inside another one that calculates avg per month, but when this query doesn't return anything, then I have an empty table as a result, but I want it to be a 0 instead, I think this result is because of the group by
select
coalesce(count(distinct t.order_id),0) as ordenes,
'Erradas' as tipo,
EXTRACT(MONTH FROM o.order_creation_date) as mes
from (
select
orders.order_id,
pd.missing ,
pd.incomplete ,
pd.damaged,
pd.status_code ,
r.reason ,
r.reason_type,
(case
when ((pd.missing is null) and (pd.incomplete is null) and (pd.damaged is null))
then NULL
when ((r.reason_type not in ('F', 'W')) and
(((pd.missing + pd.incomplete) + pd.damaged) > 0)) then 1
when ((r.reason = 'F') and (pd.missing > 0)) then 1
when ((r.reason = 'W') and (pd.missing > 0)) then 0
else 0 end) AS refund_result
from module.orders
inner join module.pack p on orders.order_id = p.order_id
inner join module.pack_d pd on p.asn = pd.asn
left join module.reason r on r.reason = p.reason
INNER JOIN module.mv_reporte mc ON orders.customer_id = mc.rut
WHERE mc.level = 'VIP'
) t
inner join ecommerce.orders o on o.order_no = t.id
where refund_result = 1
and o.order_creation_date BETWEEN '2022/01/01' AND '2022/12/31'
group by month
order by month
As you can see, I tried to use coalesce, but it didn't work
query taking 1 minute to fetch results
SELECT
`jp`.`id`,
`jp`.`title` AS game_title,
`jp`.`game_type`,
`jp`.`state_abb` AS game_state,
`jp`.`location` AS game_city,
`jp`.`zipcode` AS game_zipcode,
`jp`.`modified_on`,
`jp`.`posted_on`,
`jp`.`game_referal_amount`,
`jp`.`games_referal_amount_type`,
`jp`.`status`,
`jp`.`is_flaged`,
`u`.`id` AS employer_id,
`u`.`email` AS employer_email,
`u`.`name` AS employer_name,
`jf`.`name` AS game_function,
`jp`.`game_freeze_status`,
`jp`.`game_statistics`,
`jp`.`ats_value`,
`jp`.`integration_id`,
`u`.`account_manager_id`,
`jp`.`model_game`,
`jp`.`group_id`,
(CASE
WHEN jp.group_id != '0' THEN gm.group_name
ELSE 'NA'
END) AS group_name,
`jp`.`priority_game`,
(CASE
WHEN jp.country != 'US' THEN jp.country_name
ELSE ''
END) AS game_country,
IFNULL((CASE
WHEN
`jp`.`account_manager_id` IS NULL
OR `jp`.`account_manager_id` = 0
THEN
(SELECT
(CASE
WHEN
account_manager_id IS NULL
OR account_manager_id = 0
THEN
`u`.`account_manager_id`
ELSE account_manager_id
END) AS account_manager_id
FROM
user_user
WHERE
id = (SELECT
user_id
FROM
game_user_assigned
WHERE
game_id = `jp`.`id`
LIMIT 1))
ELSE `jp`.`account_manager_id`
END),
`u`.`account_manager_id`) AS acc,
(SELECT
COUNT(recach_limit_id)
FROM
recach_limit
WHERE
recach_limit = '1'
AND recach_limit_game_id = rpr.recach_limit_game_id) AS somewhatgame,
(SELECT
COUNT(recach_limit_id)
FROM
recach_limit
WHERE
recach_limit = '2'
AND recach_limit_game_id = rpr.recach_limit_game_id) AS verygamecommitted,
(SELECT
COUNT(recach_limit_id)
FROM
recach_limit
WHERE
recach_limit = '3'
AND recach_limit_game_id = rpr.recach_limit_game_id) AS notgame,
(SELECT
COUNT(joa.id) AS applicationcount
FROM
game_refer_to_member jrmm
INNER JOIN
game_refer jrr ON jrr.id = jrmm.rid
INNER JOIN
game_applied joa ON jrmm.id = joa.referred_by
WHERE
jrmm.STATUS = '1'
AND jrr.referby_user_id IN (SELECT
ab_testing_user_id
FROM
ab_testing)
AND joa.game_post_id = rpr.recach_limit_game_id
AND (rpr.recach_limit = 1
OR rpr.recach_limit = 2)) AS gamecount
FROM
(`game_post` AS jp)
JOIN
`user_info` AS u ON `jp`.`user_user_id` = `u`.`id`
JOIN
`game_functional` jf ON `jp`.`game_functional_id` = `jf`.`id`
LEFT JOIN
`group_musesm` gm ON `gm`.`group_id` = `jp`.`group_id`
LEFT JOIN
`recach_limit` rpr ON `jp`.`id` = `rpr`.`recach_limit_game_id`
WHERE
`jp`.`status` != '3'
GROUP BY `jp`.`id`
ORDER BY `posted_on` DESC
LIMIT 10
I would first suggest not nesting select statements because this will cause an n^x performance hit on every xth level and I see at least 3 levels of selects inside this query.
Add index
INDEX(status, posted_on)
Move LIMIT inside
Then, instead of saying
FROM (`game_post` AS jp)
say
FROM ( SELECT id FROM game_post
WHERE status != 3
ORDER BY posted_on DESC
LIMIT 10 ) AS ids
JOIN game_post AS jp USING(id)
(I am assuming that the PK of jp is (id)?)
That should efficiently use the new index to get the 10 ids needed. Then it will reach back into game_post to get the other columns.
LEFT
Also, don't say LEFT unless you need it. It costs something to generate NULLs that you may not be needing.
Is GROUP BY necessary?
If you remove the GROUP BY, does it show dup ids? The above changes may have eliminated the need.
IN(SELECT) may optimize poorly
Change
AND jrr.referby_user_id IN ( SELECT ab_testing_user_id
FROM ab_testing )
to
AND EXISTS ( SELECT * FROM ab_testing
WHERE ab_testing_user_id = jrr.referby_user_id )
(This change may or may not help, depending on the version you are running.)
More
Please provide EXPLAIN SELECT if you need further assistance.
I have following Mysql query
SELECT c.`id`
,c.`category_name`
,c.`category_type`
,c.bookmark_count
,f.category_id cat_id
,f.unfollow_at
,(
CASE WHEN c.id = f.follower_category_id
THEN (
SELECT count(`user_bookmarks`.`id`)
FROM `user_bookmarks`
WHERE (`user_bookmarks`.`category_id` = cat_id)
AND ((`f`.`unfollow_at` > `user_bookmarks`.`created_at`) || (`f`.`unfollow_at` = '0000-00-00 00:00:00'))
)
ELSE 0 END
) counter
,c.id
,f.follower_category_id follow_id
,c.user_id
FROM categories c
LEFT JOIN following_follower_categories f ON f.follower_category_id = c.id
WHERE c.user_id = 26
ORDER BY `category_name` ASC
and here is output what i am getting after execuation
now i just want to count . here i have field id having value 172 against it i have counter 30,3, 2 and Bookmark_count is 4( i need to include only once)
and i am accepting output for id 172 is 30+3+2+4(bookmark_count only once).
I am not sure how to do this.
Can anybody help me out
Thanks a lot
The following may be the most inefficient query for that purpose, but I added a cover to your query in order to hint at grouping the results.
(I removed the second c.id, and my example may have errors since I couldn't try it.)
SELECT `id`,
`category_name`,
`category_type`,
max(`bookmark_count`),
`cat_id`,
`unfollow_at`,
sum(`counter`)+max(`bookmark_count`) counter,
follow_id`, `user_id`
FROM
(SELECT c.`id`
,c.`category_name`
,c.`category_type`
,c.bookmark_count
,f.category_id cat_id
,f.unfollow_at
,(
CASE WHEN c.id = f.follower_category_id
THEN (
SELECT count(`user_bookmarks`.`id`)
FROM `user_bookmarks`
WHERE (`user_bookmarks`.`category_id` = cat_id)
AND ((`f`.`unfollow_at` > `user_bookmarks`.`created_at`) || (`f`.`unfollow_at` = '0000-00-00 00:00:00'))
)
ELSE 0 END
) counter
,f.follower_category_id follow_id
,c.user_id
FROM categories c
LEFT JOIN following_follower_categories f ON f.follower_category_id = c.id
WHERE c.user_id = 26)
GROUP BY `id`, `category_name`, `category_type`, `cat_id`, `unfollow_at`, `follow_id`, `user_id`
ORDER BY `category_name` ASC
SELECT p . * , (
SELECT (
SELECT COUNT( * )
FROM sales s
WHERE s.affiliate != ''
AND s.pid = p.pid
AND s.saletype = 'sale' )
) AS popular
FROM products p
INNER JOIN members m ON m.uname = p.vendor
WHERE (m.mpid = p.pid OR p.marketavail = 'yes')
AND p.showinmarket = 'yes'
AND p.pname != ''
AND p.pdesc != ''
AND p.active = 'yes'
ORDER BY popular DESC
Here, If i use ORDER BY popular , it takes 17 seconds to load. without this ordering , query is executed in 4 seconds.
Please tell me why it is taking too much time while ordering by virtual columns?
All tables has index on required columns, so indexing is not the issue i guess. And if i run select count(*) for single product, it is executing in milliseconds.
And one more error i saw, If i remove SELECT word (second select word in my sql), it takes 105 sec to execute.
Please tell me if i need to give any more information.
Due to such delay in sorting, i am using php instead of mysql for sorting. Please help me to make it better.
Thank you in advance.
please try this query
SELECT p.column1,
p.column2,
p.column3,
COUNT(s.pid) as popular
FROM products p
INNER JOIN members m ON m.uname = p.vendor
LEFT JOIN sales s ON s.pid = p.pid AND s.affiliate != '' AND s.saletype = 'sale'
WHERE (m.mpid = p.pid OR p.marketavail = 'yes')
AND p.showinmarket = 'yes'
AND p.pname != ''
AND p.pdesc != ''
AND p.active = 'yes'
GROUP BY p.column1,p.column2,p.column3
ORDER BY popular DESC
column1,column2,column3 are just examples of columns you want, because you're select * I don't know what column names are from product. so change them to your actual column names.
edit: try this query see if it's any faster
SELECT p.pname, p.vendor, p.pid,
COUNT( s.pid ) AS popular
FROM products p INNER JOIN members m ON m.uname = p.vendor
LEFT JOIN
(SELECT pid FROM sales
WHERE affiliate != ''
AND saletype = 'sale'
)s
ON (s.pid = p.pid)
WHERE ( m.mpid = p.pid OR p.marketavail = 'yes' )
AND p.showinmarket = 'yes' AND p.pname != ''
AND p.pdesc != ''
AND p.active = 'yes'
GROUP BY p.pid, p.pname
ORDER BY popular DESC
if it runs faster you can pre-filter products too like this query and see if it runs even faster
SELECT p.pname, p.vendor, p.pid,
COUNT( s.pid ) AS popular
FROM (SELECT pname,vendor,pid,marketavail
FROM products
WHERE showinmarket = 'yes'
AND pname != ''
AND pdesc != ''
AND active = "yes"
)p
INNER JOIN members m ON m.uname = p.vendor
LEFT JOIN
(SELECT pid FROM sales
WHERE affiliate != ''
AND saletype = 'sale'
)s
ON (s.pid = p.pid)
WHERE ( m.mpid = p.pid OR p.marketavail = 'yes' )
GROUP BY p.pid, p.pname
ORDER BY popular DESC
Can you please help me optimize this query. I use this query to get a list of friends along with their details and their status.
It takes about 0.08 secs to process this on a Athlon X2 6000
I cant use materizlized view as well because this is frequently changing.
SELECT p.userid, p.firstname, p.lastname, p.gender, p.dob, x.relationship,
IF(p.picture !=1,
IF(p.gender != 'm','/sc/f-t.jpg','/sc/m-t.jpg'),
concat('/sc/pthumb/', p.userid, '.jpg' )) AS picture
FROM `social` AS p
LEFT JOIN `friendlist` AS f1 ON (f1.`userid` = p.`userid` AND f1.`friendid` = 1 AND `f1`.`status` = 1)
LEFT JOIN `friendlist` AS f2 ON (f2.`friendid` = p.`userid` AND f2.`userid` = 1 AND `f2`.`status` = 1)
LEFT JOIN `x_relationship` AS x ON (x.`id` = p.`relationship`)
LEFT JOIN `auth` as a ON (a.`userid` = p.`userid`)
WHERE 1 AND (f1.`userid` IS NOT NULL OR f2.`userid` IS NOT NULL AND ((a.`banned` != 1 AND a.`deleted` != 1)))
ORDER BY RAND() LIMIT 0,10
This is your original query, formatted. Below it are a few thoughts.
SELECT
p.userid,
p.firstname,
p.lastname,
p.gender,
p.dob,
x.relationship,
IF(p.picture !=1, IF(p.gender != 'm', '/sc/f-t.jpg', '/sc/m-t.jpg'), concat('/sc/pthumb/', p.userid, '.jpg' )) AS picture
FROM
`social` AS p
LEFT JOIN `friendlist` AS f1 ON (f1.`friendid` = 1 AND f1.`userid` = p.`userid` AND `f1`.`status` = 1)
LEFT JOIN `friendlist` AS f2 ON (f2.`friendid` = p.`userid` AND f2.`userid` = 1 AND `f2`.`status` = 1)
LEFT JOIN `x_relationship` AS x ON (x.`id` = p.`relationship`)
LEFT JOIN `auth` AS a ON (a.`userid` = p.`userid`)
WHERE
1
AND (
f1.`userid` IS NOT NULL
OR f2.`userid` IS NOT NULL
AND (a.`banned` != 1 AND a.`deleted` != 1)
)
ORDER BY
RAND()
LIMIT
0,10
Think if some of your left joins could be inner joins. If so, change them.
Your WHERE clause is messed up. You are mixing AND and OR without properly prioritizing with parentheses. Try:
WHERE
a.`banned` != 1
AND a.`deleted` != 1
AND (
f1.`userid` IS NOT NULL
OR f2.`userid` IS NOT NULL
)
You could also try:
INNER JOIN `auth` AS a ON (
a.`userid` = p.`userid`
AND a.`banned` != 1
AND a.`deleted` != 1
)
WHERE
f1.`userid` IS NOT NULL
OR f2.`userid` IS NOT NULL
You seem to be joining against friendlist solely to check for record existence. You might want to give this a try as well:
FROM
`social` AS p
INNER JOIN `auth` AS a ON (
a.`userid` = p.`userid`
AND a.`banned` != 1
AND a.`deleted` != 1
)
LEFT JOIN `x_relationship` AS x ON (
x.`id` = p.`relationship`
)
WHERE
EXISTS (
SELECT 1 FROM `friendlist` WHERE `friendid` = 1 AND `userid` = p.`userid` AND `status` = 1
)
OR EXISTS (
SELECT 1 FROM `friendlist` WHERE `friendid` = p.`userid` AND `userid` = 1 AND `status` = 1
)
ORDER BY RAND() might not be the fastest thing on earth, but if this is what you need... Try ordering by a indexed column to see how much impact ORDER BY RAND() has.
Indexing:
You should create a composite index on friendlist(friendid, userid, status).
Make sure there is an index on relationship(id)
Make sure there is an index on auth(userid)