Anyone can help me, I am a bit stuck.
I have this query which works like a charm
SELECT * ,
matches - falsepositives AS hits
FROM (
SELECT c. * ,
IFNULL( p.total, 0 ) AS matches,
(
SELECT COUNT( * )
FROM ci_falsepositives n
WHERE n.addressbook_id = c.reference
AND n.sanction_key
IN (
SELECT sanction_key
FROM ci_matched_sanctions
)
) AS falsepositives
FROM ci_address_book c
LEFT JOIN (
SELECT addressbook_id,
COUNT( match_id ) AS total
FROM ci_matched_sanctions
GROUP BY addressbook_id
) AS p
ON c.id = p.addressbook_id
) AS S
WHERE matches > 0
ORDER BY hits DESC
But I would like to change it to sort where HITS are more than 0, but it tells me it doesn't know hits... Is it because it's a calculation of 2 items?
You can't use an aliases column in a WHERE clause. You need to rewrite it:
SELECT * ,
matches - falsepositives AS hits
FROM (
SELECT c. * ,
IFNULL( p.total, 0 ) AS matches,
(
SELECT COUNT( * )
FROM ci_falsepositives n
WHERE n.addressbook_id = c.reference
AND n.sanction_key
IN (
SELECT sanction_key
FROM ci_matched_sanctions
)
) AS falsepositives
FROM ci_address_book c
LEFT JOIN (
SELECT addressbook_id,
COUNT( match_id ) AS total
FROM ci_matched_sanctions
GROUP BY addressbook_id
) AS p
ON c.id = p.addressbook_id
) AS S
WHERE matches - falsepositives > 0
ORDER BY hits DESC
Or use a subquery:
SELECT * FROM (
SELECT * ,
matches - falsepositives AS hits
FROM (
SELECT c. * ,
IFNULL( p.total, 0 ) AS matches,
(
SELECT COUNT( * )
FROM ci_falsepositives n
WHERE n.addressbook_id = c.reference
AND n.sanction_key
IN (
SELECT sanction_key
FROM ci_matched_sanctions
)
) AS falsepositives
FROM ci_address_book c
LEFT JOIN (
SELECT addressbook_id,
COUNT( match_id ) AS total
FROM ci_matched_sanctions
GROUP BY addressbook_id
) AS p
ON c.id = p.addressbook_id
) AS S
) AS S2
WHERE hits > 0
ORDER BY hits DESC
Related
I am trying to optimize a SQL query and I would like some expert opinion on the best/fastest way to combine GROUP BY and ORDER BY
Basically I am trying to select the lowest price from a products table and group them by merchant name.
This was my original query:
select p.*, m.*, d.* from datafeeds as d, products as p left outer join meta as m on p.mykey = m.mykey where p.datafeed_id = d.id and (match(p.name) against ('+asics +"gel" -women*' in boolean mode)) and p.datafeed_id = '35' and p.is_custom = 0 group by d.merchant_name order by d.merchant_name limit 50
And the ORDER BY was not working, I was getting grouped products but not the ones with the lowest prices.
After reading other discussions i came up with an improved query:
SELECT p . * , m . * , d . *
FROM datafeeds AS d, products AS p
INNER JOIN (
SELECT MIN( display_price ) AS MinPrice
FROM products AS p
WHERE 1 =1
AND (
MATCH (
p.name
)
AGAINST (
'+asics +"gel" -women*'
IN BOOLEAN
MODE
)
)
AND p.datafeed_id = '35'
AND p.is_custom =0
GROUP BY merchant_name
) AS p2 ON p.display_price = p2.MinPrice
LEFT OUTER JOIN meta AS m ON p.mykey = m.mykey
WHERE p.datafeed_id = d.id
AND (
MATCH (
p.name
)
AGAINST (
'+asics +"gel" -women*'
IN BOOLEAN
MODE
)
)
AND p.datafeed_id = '35'
AND p.is_custom =0
GROUP BY d.merchant_name
ORDER BY d.merchant_name
LIMIT 50`
The query gets the correct results but it is quite slow.
Is there a better way to do it?
Thanks in advance
You could try this
SELECT p.*,
m.*,
d.*
FROM datafeeds AS d,
(
SELECT *
FROM products
WHERE 1 = 1
AND (
MATCH ( name ) against ( '+asics +"gel" -women*' IN boolean mode ) )
AND datafeed_id = '35'
AND is_custom =0
ORDER BY merchant_name,
display_price) AS p
LEFT OUTER JOIN meta AS m
ON p.mykey = m.mykey
WHERE p.datafeed_id = d.id
GROUP BY d.merchant_name
ORDER BY d.merchant_name
LIMIT 50
I want to add data from table b in table a but unfortunately full outer join do not work in mysql . I have also tried union but it is throwing errors because my statement has group by and order by keyword
SELECT COUNT( ReviewedBy ) AS TotalReviews, OrganizationId, SUM( Rating ) AS TotalStars, COUNT( Rating ) AS TotalRatings, (
SUM( Rating ) / COUNT( Rating )
) AS AverageRating
FROM `tbl_reviews`
WHERE ReviewType = 'shopper'
AND ReviewFor = 'org'
AND OrganizationId
IN (
SELECT OrganizationId
FROM tbl_organizations
WHERE CategoryID =79
)
GROUP BY OrganizationId
ORDER BY AverageRating DESC
This is what i'm getting from the above statement
I want to get organizationId 21 data in the result but i'm not getting result because it's not present in 'tbl_review' table
click here to see the table b
How can i get Desired result ?
You don't need a FULL, but a LEFT join:
SELECT COUNT( ReviewedBy ) AS TotalReviews, o.OrganizationId,
SUM( Rating ) AS TotalStars, COUNT( Rating ) AS TotalRatings,
(SUM( Rating ) / COUNT( Rating )) AS AverageRating
FROM tbl_organizations AS o
LEFT JOIN `tbl_reviews` AS r
ON o.OrganizationId = r.OrganizationId
AND ReviewType = 'shopper' -- conditions on inner table
AND ReviewFor = 'org' -- must be moved to ON
WHERE CategoryID =79
GROUP BY o.OrganizationId
ORDER BY AverageRating DESC
Why don't you use AVG instead of SUM/COUNT?
Have you tried:
from organization
left outer join tbl_reviews
on organization.ID = tbl_reviews.organization is
for your where clause? I don't think you need a full outer join in this case... A left outer join should do
I want to fetch four records from two table.
Two takes some of the records and two takes count of the record.
SELECT sum( a.user_follower_count ) AS mention_reach,
count( a.sno ) AS mention_count,
sum( b.user_follower_count ) AS retweet_reach,
count( b.username ) AS count_retweet
FROM twitter_mention AS a, twitter_retweet AS b
Here mention_reach and retweet_reach are fetched correctly, but count values are comming wrong?
IS there anything wrong here?
I have only 6 records twitter_mention and 10 in twitter_retweet, but it gives 60 for both count values.
There is no JOIN between your tables a and b.
Add JOIN b ON
Or add explicit join in WHERE section
UPDATE
select *
from
(SELECT
sum( a.user_follower_count ) AS mention_reach,
count( a.sno ) AS mention_count
FROM twitter_mention AS a) a,
(SELECT
sum( b.user_follower_count ) AS retweet_reach,
count( b.username ) AS count_retweet
FROM twitter_retweet AS b) b
Your code is doing a full join, which says.
For every record in table a, give me all records in table b.
SELECT sum( a.user_follower_count ) AS mention_reach,
count( a.sno ) AS mention_count,
sum( b.user_follower_count ) AS retweet_reach,
count( b.username ) AS count_retweet
FROM twitter_mention AS a, twitter_retweet AS b
What you need to do, is determine which record in table b you want for each record in table a, not all of them. This is done via the ON clause on the join
SELECT sum( a.user_follower_count ) AS mention_reach,
count( a.sno ) AS mention_count,
sum( b.user_follower_count ) AS retweet_reach,
count( b.username ) AS count_retweet
FROM twitter_mention AS a
JOIN twitter_retweet AS b ON a.<somefield> = B.<somefield>
Also, you syntax for a JOIN should be updated to using the JOIN keyword. You can see the JOIN syntax is my second query above.
If you don't have any common keys, I would recommend two queries using a UNION clause, i.e.
SELECT 'MENTION' as Type,sum( a.user_follower_count ) AS reach,
count( a.sno ) AS count
FROM twitter_mention AS a
UNION
SELECT 'RETWEET' as Type,sum( b.user_follower_count ) ,
count( b.username )
FROM twitter_retweet AS b
I have following two queries
1)
SELECT `domains`.`name` , `pageviews`.`domain_id` , COUNT( `pageviews`.`domain_id` )
FROM `pageviews`
LEFT JOIN `domains` ON ( `domains`.`id` = `pageviews`.`domain_id`
AND `domains`.`user_id` = '129' )
WHERE `pageviews`.`user_id` = '129'
GROUP BY `pageviews`.`domain_id`
ORDER BY COUNT( `pageviews`.`domain_id` ) DESC
2)
SELECT `domains`.`name` , `visitors`.`ip` , `visitors`.`domain_id` , COUNT( `visitors`.`domain_id` )
FROM `visitors`
LEFT JOIN `domains` ON ( `domains`.`id` = `visitors`.`domain_id`
AND `domains`.`user_id` = '129' )
WHERE `visitors`.`user_id` = '129'
GROUP BY `visitors`.`domain_id`
ORDER BY COUNT( `visitors`.`domain_id` ) DESC
I want to combine these queries.
this is required for cakephp pagination because i want to show data in table and want to sort acc. to visitors and pageviews if i want.
associations are 1) domains has many visitors 2) domains has many pageviews
Try this:
SELECT
pv.name,pv.domain_id,pv.counter as page_visits, v.ip, v.counter as visits
FROM (
SELECT `domains`.`name` , `pageviews`.`domain_id` , COUNT( `pageviews`.`domain_id` ) as counter
FROM `pageviews`
LEFT JOIN `domains` ON ( `domains`.`id` = `pageviews`.`domain_id`
AND `domains`.`user_id` = '129' )
WHERE `pageviews`.`user_id` = '129'
GROUP BY `pageviews`.`domain_id`
ORDER BY COUNT( `pageviews`.`domain_id` ) DESC
) as pv
LEFT JOIN (
SELECT `domains`.`name` , `visitors`.`ip` , `visitors`.`domain_id` , COUNT( `visitors`.`domain_id` ) as counter
FROM `visitors`
LEFT JOIN `domains` ON ( `domains`.`id` = `visitors`.`domain_id`
AND `domains`.`user_id` = '129' )
WHERE `visitors`.`user_id` = '129'
GROUP BY `visitors`.`domain_id`
ORDER BY COUNT( `visitors`.`domain_id` ) DESC
) as v
ON pv.domain_id = v.domain_id
I have a MySQL query like this:
SELECT *
FROM backstage
WHERE backstage_id IN (
SELECT backstage_id
FROM visitor_counter
WHERE backstage_id !=0
GROUP BY backstage_id
ORDER BY COUNT( DISTINCT ( ip_address ) ) DESC
)
LIMIT 0 , 100
I get the results I want, but I would like to order it by COUNT( DISTINCT ( ip_address ) ) DESC as the inner question does.
Any tips on how to do this?
Give this a go and see if it gives you what you're after:
select bs.*
from backstage bs
inner join
(
select backstage_id,count(distinct ip_address) as distIpCount
from visitor_counter
where backstage_id !=0
group by backstage_id
) vc on vc.backstage_id = bs.backstage_id
order by vc.distIpCount desc
limit 0,100;