Mysql left join same table sum wrong results - mysql

I have a problem with a query which should do the following:
Get specific records and calculate some of their values for specific period of time
Calculate same values of these keywords for another period of time
This should happen into 1 query. I was able to write it but SUM() returns wrong value much higher than normal. I think that this is because of LEFT JOIN.
SELECT SQL_CALC_FOUND_ROWS table1.id, table1.KeywordId, table1.AccountName, table1.CampaignName, table1.AdGroupName, table1.Keyword, table1.MatchType, SUM(table1.Spend)/SUM(table1.Clicks) AS AverageCpc, SUM(table1.Impressions) AS Impressions, (SUM(table1.Clicks)*table1.revenue_price)/SUM(table1.Impressions) AS Ctr, SUM(table1.Impressions*table1.AveragePosition)/SUM(table1.Impressions) AS AveragePosition, SUM(table1.Clicks) AS Clicks, SUM(table1.Spend) AS Spend, SUM(table1.free_joins) AS FreeJoins, SUM(table1.paid_joins) AS PaidJoins, SUM(table1.paid_joins)*table1.revenue_price AS Revenue, (SUM(table1.paid_joins)*table1.revenue_price)-SUM(table1.Spend) AS Profit, (SUM(table1.paid_joins)*table1.revenue_price)/SUM(table1.Clicks) AS RevPerClick, table1.CurrentMaxCpc, SUM(table2.Impressions) AS Impressions_chg, SUM(table2.Clicks) AS Clicks_chg, SUM(table2.Impressions*table2.AveragePosition)/SUM(table2.Impressions) AS AveragePosition_chg, (SUM(table2.Clicks)*table2.revenue_price)/SUM(table2.Impressions) AS Ctr_chg, SUM(table2.Spend)/SUM(table2.Clicks) AS AverageCpc_chg, table2.CurrentMaxCpc as CurrentMaxCpc_chg, SUM(table2.free_joins) AS FreeJoins_chg, SUM(table2.paid_joins) AS PaidJoins_chg
FROM keywords_stats_google_naughtymeetings as table1
LEFT JOIN keywords_stats_google_naughtymeetings as table2
ON table1.keywordId = table2.keywordId
WHERE table1.timeperiod >= '2012-05-21 00:00:00' and table1.timeperiod <= '2012-05-27 00:00:00'
AND table2.timeperiod >= '2012-05-14' and table2.timeperiod <= '2012-05-20'
GROUP BY table1.KeywordId, table1.MatchType, table1.revenue_price, table2.KeywordId, table2.MatchType, table2.revenue_price
ORDER BY FreeJoins
asc
LIMIT 0, 10
Can someone give me an advice how I can get correct SUM results?

I think you need INNER JOIN here. Try to replace the LEFT JOIN with INNER JOIN.
P.S.
I don't get exactly what you want, but I think this idea should be simpler.
(SELECT id, fields_for_first_period_of_time
FROM keywords_stats_google_naughtymeetings) t1
JOIN
(SELECT id, fields_for_second_period_of_time
FROM keywords_stats_google_naughtymeetings) t2
ON t1.id = t2.id
This is just a sketch of the idea. I mean get the results with two separate queries. And then join them. This will be easier for debugging. I hope this can help you.

Related

Return column value without aggregation for grouped query

Ok, question sound very confusing, I just can't come up with better title.
Here is my query:
SELECT TS.LocationKey, TA.TrailerKey, MAX(TS.ArrivedOnLocal) MaxArrivedOnLocal
FROM dbo.DSPTripStop TS
INNER JOIN dbo.DSPTripAssignment TA ON TS.TripStopKey = TA.ToTripStopKey AND TA.TrailerKey IS NOT NULL
GROUP BY TS.LocationKey, TA.TrailerKey
Query returns list of trailers with locations and last time they were dropped at that location. This is what I need. MAX(time) for location is a goal.
But I'd like to also know which DSPTripStop.TripStopKey this MAX() time happened on.
I can't group by this value. I understand that it is not defined (can be multiple values for the same time). For my purpose ANY random will work. But I can't find any better way then joining second time by MaxArrivedOnLocal to get what I need.
SQL Server already "sees" this data when MAX() aggregated, any way to pull it in this query?
I think this is what you want. Rather than doing a group by, you partition instead, number the rows, then take the top 1
WITH cte AS
(
SELECT TS.LocationKey,
TA.TrailerKey,
TS.ArrivedOnLocal,
TS.TripStopKey,
ROW_NUMBER() OVER (PARTITION BY TS.LocationKey, TA.TrailerKey ORDER BY ArrivedOnLocal DESC) rn
FROM dbo.DSPTripStop TS
INNER JOIN dbo.DSPTripAssignment TA ON TS.TripStopKey = TA.ToTripStopKey AND TA.TrailerKey IS NOT NULL
)
SELECT LocationKey,
TrailerKey,
ArrivedOnLocal,
TripStopKey
FROM cte
WHERE rn = 1
If you need any random value for DSPTripStop.TripStopKey then you can use MAX itself as this will return the latest TripStopKey.
SELECT
TS.LocationKey,
TA.TrailerKey,
MAX(TS.ArrivedOnLocal) MaxArrivedOnLocal,
MAX(TS.TripStopKey)
FROM dbo.DSPTripStop TS
INNER JOIN dbo.DSPTripAssignment TA
ON TS.TripStopKey = TA.ToTripStopKey
AND TA.TrailerKey IS NOT NULL
GROUP BY TS.LocationKey, TA.TrailerKey

MySQL Query....tricky counts.. not sure how to combine

i need help with this query.. i keep stats for a First Person Shooter.
The data looks like this:
I've am this far with the query:
SELECT
a.name,p.killer as killer_id, ROUND(AVG(p.distance)) as average_distance,p.bambikill,
(Select count(killer)) as total_kills,
(Select count(bambikill) where bambikill = 1)as newbiekills
FROM
player_stats p
inner join account a on p.killer = a.uid
group by killer_id
The result of the
What i need to do next is get the deaths of the player 'killer' which woudl be in the victim column and count for all that player's deaths. Each time he's shown up tin the victim column.
Is this possible? I've tried a few combinations but can't seem to get it right. I'm not the best with MySQL queries.
One option to determine the number of times a killer has himself been killed is to use a subquery which aggregates over the victim column. Then LEFT JOIN your current query to this subquery. Note that LEFT JOIN is used to allow for the possibility that a killer never in fact gets killed. In this case, COALESCE would report zero for this stat.
SELECT t2.name,
t1.killer_id,
t1.average_distance,
t1.total_kills,
t1.newbiekills,
COALESCE(t3.numKills, 0) AS num_times_killed
FROM
(
SELECT p.killer AS killer_id,
ROUND(AVG(p.distance)) AS average_distance,
COUNT(*) AS total_kills,
SUM(p.bambikill) AS newbiekills
FROM player_stats p
GROUP BY p.killer
) t1
INNER JOIN account t2
ON t1.killer = t2.uid
LEFT JOIN
(
SELECT victim, COUNT(*) AS numKills
FROM player_stats
GROUP BY victim
) t3
ON t1.killer = t3.victim
GROUP BY t1.killer

How to fix SQL query with Left Join and subquery?

I have SQL query with LEFT JOIN:
SELECT COUNT(stn.stocksId) AS count_stocks
FROM MedicalFacilities AS a
LEFT JOIN stocks stn ON
(stn.stocksIdMF = ( SELECT b.MedicalFacilitiesIdUser
FROM medicalfacilities AS b
WHERE b.MedicalFacilitiesIdUser = a.MedicalFacilitiesIdUser
ORDER BY stn.stocksId DESC LIMIT 1)
AND stn.stocksEndDate >= UNIX_TIMESTAMP() AND stn.stocksStartDate <= UNIX_TIMESTAMP())
These query I want to select one row from table stocks by conditions and with field equal value a.MedicalFacilitiesIdUser.
I get always count_stocks = 0 in result. But I need to get 1
The count(...) aggregate doesn't count null, so its argument matters:
COUNT(stn.stocksId)
Since stn is your right hand table, this will not count anything if the left join misses. You could use:
COUNT(*)
which counts every row, even if all its columns are null. Or a column from the left hand table (a) that is never null:
COUNT(a.ID)
Your subquery in the on looks very strange to me:
on stn.stocksIdMF = ( SELECT b.MedicalFacilitiesIdUser
FROM medicalfacilities AS b
WHERE b.MedicalFacilitiesIdUser = a.MedicalFacilitiesIdUser
ORDER BY stn.stocksId DESC LIMIT 1)
This is comparing MedicalFacilitiesIdUser to stocksIdMF. Admittedly, you have no sample data or data layouts, but the naming of the columns suggests that these are not the same thing. Perhaps you intend:
on stn.stocksIdMF = ( SELECT b.stocksId
-----------------------------^
FROM medicalfacilities AS b
WHERE b.MedicalFacilitiesIdUser = a.MedicalFacilitiesIdUser
ORDER BY b.stocksId DESC
LIMIT 1)
Also, ordering by stn.stocksid wouldn't do anything useful, because that would be coming from outside the subquery.
Your subquery seems redundant and main query is hard to read as much of the join statements could be placed in where clause. Additionally, original query might have a performance issue.
Recall WHERE is an implicit join and JOIN is an explicit join. Query optimizers
make no distinction between the two if they use same expressions but readability and maintainability is another thing to acknowledge.
Consider the revised version (notice I added a GROUP BY):
SELECT COUNT(stn.stocksId) AS count_stocks
FROM MedicalFacilities AS a
LEFT JOIN stocks stn ON stn.stocksIdMF = a.MedicalFacilitiesIdUser
WHERE stn.stocksEndDate >= UNIX_TIMESTAMP()
AND stn.stocksStartDate <= UNIX_TIMESTAMP()
GROUP BY stn.stocksId
ORDER BY stn.stocksId DESC
LIMIT 1

MySQL Syntax Issue combining to working queries

I'm just starting to learn SQL, and managed to cobble together a couple of working queries, but then when I combine them I am getting a syntax error. The query throwing the error:
SELECT sca_ticket_status.name As Status, AVG(QueueTime)
FROM (SELECT DateDiff (created, now()) as 'QueueTime'
FROM sca_ticket as SubQuery
LEFT JOIN sca_ticket_status
ON sca_ticket.status_id = sca_ticket_status.id
GROUP BY name
ORDER BY sort
For reference, the two working queries that I am attempting to leverage are as follows:
SELECT sca_ticket_status.name As Status, COUNT(sca_ticket.ticket_id) AS Count
FROM sca_ticket
LEFT JOIN sca_ticket_status
ON sca_ticket.status_id = sca_ticket_status.id
WHERE sca_ticket.created between date_sub(now(),INTERVAL 1 WEEK) and now()
GROUP BY name
ORDER BY sort
SELECT AVG(QueueTime)
FROM (SELECT DateDiff (created, now()) as 'QueueTime'
FROM `sca_ticket`
WHERE `status_id` = 1) as SubQuery
Try closing your second select statement
SELECT sca_ticket_status.name As Status, AVG(QueueTime)
FROM (SELECT status_id, DateDiff (created, now()) as 'QueueTime'
FROM sca_ticket) q1
LEFT JOIN sca_ticket_status
ON q1.status_id = sca_ticket_status.id
GROUP BY name
ORDER BY sort
You will also need to expose the status_id column in your inner select list if you want to join on it later.
You do not need a subquery at all. This just slows down the processing in MySQL (the optimizer is not very smart; it materializes subqueries losing index information).
SELECT ts.name As Status, AVG(DateDiff(t.created, now()))
FROM sca_ticket t LEFT JOIN
sca_ticket_status ts
ON t.status_id = ts.id
GROUP BY ts.name
ORDER BY sort

Alternative to mysql WHERE IN SELECT GROUP BY when wanting max value in group by

I have the following query, which was developed from a hint found online because of a problem with a GROUP BY returning the maximum value; but it's running really slowly.
Having looked online I'm seeing that WHERE IN (SELECT.... GROUP BY) is probably the issue, but, to be honest, I'm struggling to find a way around this:
SELECT *
FROM tbl_berths a
JOIN tbl_active_trains b on a.train_uid=b.train_uid
WHERE (a.train_id, a.TimeStamp) in (
SELECT a.train_id, max(a.TimeStamp)
FROM a
GROUP BY a.train_id
)
I'm thinking I possibly need a derived table, but my experience in this area is zero and it's just not working out!
you can move that to a SUBQUERY and also select only required columns instead of All (*)
SELECT a.train_uid
FROM tbl_berths a
JOIN tbl_active_trains b on a.train_uid=b.train_uid
JOIN (SELECT a.train_id, max(a.TimeStamp) as TimeStamp
FROM a
GROUP BY a.train_id )T
on a.train_id = T.train_id
and a.TimeStamp = T.TimeStamp