Updated:
Here is the demo and current result based on M Khalid Junaid's answer. The query still doesn't output my expected result.
I have a very simple table and here is the values.
id animal_id latitude longitude created_at
--------------------------------------------------------------------------
119 75 1.356203 103.828140 2014-04-30 15:00:04
118 75 1.296613 103.857079 2014-04-30 14:58:58
117 75 1.296613 103.857079 2014-04-30 14:58:20
116 75 1.296613 103.857079 2014-04-30 14:53:17
Here is my query and I want to GROUP if latitude, longitude and user_id is same.
select p.id,p.animal_id,p.name,p.latitude,p.longitude,p.created_at from Photo p
where 5 >= (select count(*)
from Photo p2
where p2.animal_id = p.animal_id and
p2.id <= p.id
)
AND DATE(p.created_at) > DATE_SUB(NOW(),INTERVAL 13 DAY)
AND ( p.latitude BETWEEN 0.908862 AND 1.717581 ) AND ( p.longitude BETWEEN 103.584595 AND 104.098206 )
GROUP BY p.latitude,p.longitude,p.animal_id
ORDER BY p.created_at DESC;
Current result id = 116
id animal_id latitude longitude created_at
--------------------------------------------------------------------------
119 75 1.356203 103.828140 2014-04-30 15:00:04
116 75 1.296613 103.857079 2014-04-30 14:53:17
Expected result id = 118
I want to get most recent result when I group latitude,longitude,uer_id
id animal_id latitude longitude created_at
--------------------------------------------------------------------------
119 75 1.356203 103.828140 2014-04-30 15:00:04
118 75 1.296613 103.857079 2014-04-30 14:58:58
I've tried several ways but couldn't get the desired result.
Use a self join,results from group by are indeterminate and can't guarantee you the latest row for the group
select p.id,p.animal_id,
p.latitude,p.longitude,p.created_at
from Photo p
JOIN (SELECT MAX(id) id,latitude,longitude,animal_id
FROM Photo
GROUP BY latitude,longitude,animal_id
) p1 ON(p.id = p1.id)
where 5 >= (select count(*)
from Photo p2
where p2.animal_id = p.animal_id and
p2.id <= p.id)
AND DATE(p.created_at) > DATE_SUB(NOW(),INTERVAL 13 DAY)
AND ( p.latitude BETWEEN 0.908862 AND 1.717581 )
AND ( p.longitude BETWEEN 103.584595 AND 104.098206 )
GROUP BY p.latitude,p.longitude,p.animal_id
ORDER BY p.created_at DESC;
Demo
Finally I've managed to find my own answer. Thanks everyone for sharing your time.
SELECT p.id,p.animal_id,p.latitude,p.longitude,p.created_at
-- This will make sure that `GROUP BY` will pickup most recent result
FROM (SELECT id,animal_id,latitude,longitude,created_at from Photo ORDER BY id DESC) p
-- Pick 5 rows for each animal_id. Meaning, there can be multiple photo of animal but MAX is 5.
WHERE 5 >= (select count(*)
from (SELECT * from Photo p4 GROUP BY latitude,longitude,animal_id) p2
where p2.animal_id = p.animal_id and
p2.id >= p.id
)
-- We want Photos uploaded 5 days ago
AND DATE(p.created_at) > DATE_SUB(NOW(),INTERVAL 15 DAY)
-- Plus, only photos within given Map Bound
AND ( p.latitude BETWEEN 0.908862 AND 1.717581 ) AND ( p.longitude BETWEEN 103.584595 AND 104.098206 )
-- This will help to remove duplicate images in same location of same animal. We will see only most recent photo in each exact lat,lng location
GROUP BY p.latitude,p.longitude,p.animal_id
ORDER BY id DESC;
It's may be tricky solution. You can concatenate latitude,longitude,animal_id in the group statement like this :
group by concat(latitude, longitude, animal_id)
Related
Hi I have this table.
id lat lng userId
1 12 23 1
2 45 34 2
3 42 34 3
4 33 34 1
5 36 79 2
6 53 98 2
7 23 90 3
8 23 67 1
Here we have three users. (user ids 1,2,3). I want to get lateset record (id column max value) of each user.
My excepted output is this
userId lat lng
1 23 67
2 53 98
3 23 90
This query will give me group by option
SELECT
*
FROM
covid.locations
GROUP BY userId;
But how do I combine this with MAX(id) function.
One way is to use the following:
SELECT
cl.*
FROM covid.locations cl
INNER JOIN (
SELECT
userid
, MAX( id ) mid
FROM covid.locations
GROUP BY
userId
) g ON cl.userid = g.userid
AND cl.id = cl.mid
Another is to use row_number() over()
SELECT
userId
, lat
, lng
FROM (
SELECT
*
, ROW_NUMBER() OVER (PARTITION BY userid ORDER BY id DESC) rn
FROM covid.locations
GROUP BY
userId
) d
WHERE rn = 1
Both will identify the "most recent" row in the source table based in the id column of that table. Note that the second query requires MySQL version 8+ as this is when row_number() became supported in that database. The first query should run in dbms supporting SQL.
This will do
SELECT
*
FROM
covid.locations
where id in (select max(t.id) from covid.locations t group by t.userId)
order by id desc;
An example of the above query can be found in this SQLFiddle
SELECT
points.location_id,
route_locations.route_id
FROM
points
LEFT JOIN route_locations ON route_locations.location_id = points.location_id
WHERE
points.id = 199 OR points.id = 205
after this query I am getting this result..
route_id location_id
12 69
12 75
14 75
now I need the common value for location_id 69 and location_id 75.. ( here route_id 12)
How can I get that by Query..
You can try below query -
SELECT
route_locations.route_id
FROM points
JOIN route_locations ON route_locations.location_id = points.location_id
WHERE
points.id in (199,205)
group by route_locations.route_id
having count(points.location_id)=2
I am trying to sort the transaction dates into an aging policy. When LastDate has been in the location for greater than Aging Days limit policy it should show up as OverAge if not Within referring to the current date.
Here is the current table:
+---------+------+----------+-------------+
|LastDate | Part | Location | Aging Days |
+---------+------+----------+-------------+
12/1/2016 123 VVV 90
8/10/2017 444 RRR 10
8/01/2017 144 PR 21
7/15/2017 12 RRR 10
Here is the query:
select
q.lastdate,
r.part, r.location,
a.agingpolicy as 'Aging Days'
from opsintranexcel r (nolock)
left InventoryAging a (nolock) on r.location=a.location
left join (select part,MAX(trandate) as lastdate from opsintran group by
part) q on r.part=q.part
Here is the extra column I want added in:
+---------+------+----------+------------+---------+
|LastDate | Part | Location | Aging Days | Age |
+---------+------+----------+------------+---------+
12/1/2016 123 VVV 90 Overage
8/10/2017 444 RRR 10 Within
8/01/2017 144 PR 21 Within
7/15/2017 12 RRR 10 Overage
I appreciate your help.
I think below code will be work for you
SELECT
q.lastdate,
r.part,
r.location,
a.agingpolicy as 'Aging Days'
'Age' =
CASE
WHEN DATEDIFF( day, q.LastDate, GETDATE() ) > a.agingpolicy THEN 'Overage'
ELSE THEN 'Within'
END
FROM opsintranexcel r (nolock)
LEFT JOIN InventoryAging a (nolock) on r.location=a.location
LEFT JOIN (
SELECT part,MAX(trandate) as lastdate
FROM opsintran
WHERE trantype='II' and PerPost>='201601'
GROUP BY part) q ON r.part=q.part
you can check the difference of the current date and the lastdate value if over or within the aging days
CASE WHEN DATEDIFF(NOW(), q.lastdate) > a.agingpolicy
THEN 'Overage'
ELSE 'Within'
END AS age
You should modify your query as:
select
q.lastdate,
r.part, r.location,
a.agingpolicy as 'Aging Days',
if(DATEDIFF(NOW(), q.lastdate)) > a.agingpolicy, 'Overage','Within') as 'Age'
from opsintranexcel r (nolock)
left InventoryAging a (nolock) on r.location=a.location
left join (select part,MAX(trandate) as lastdate from opsintran where
trantype='II' and PerPost>='201601' group by part) q on r.part=q.part
Table 1:
Date PlacementID CampaignID Impressions
04/01/2014 100 10 1000
04/01/2014 101 10 1500
04/01/2014 100 11 500
Table 2:
Date PlacementID CampaignID Cost
04/01/2014 100 10 5000
04/01/2014 101 10 6000
04/01/2014 100 11 7000
04/01/2014 103 10 8000
When I have joined this table using Full Join and Left Join statement, I am not able to get uncommon record which is last row in table2 that display PlacementID 103 and campaignID 10 and Cost 8000. However I have searched all raw data and file but this missing records are not common between two sources. However, I want to include this records in final table. How can I do that? This two table are two different source and I have got results only common records.
Moreover, when I found out that missing value is exact value that are required in final figure so want to include every thing. I am including my SQL script below:
SELECT A.palcementid,
A.campaignid,
A.date,
Sum(A.impressions) AS Impressions,
Sum(CASE
WHEN C.placement_count > 1 THEN ( B.cost / C.placement_count )
ELSE B.cost
END) AS Cost
FROM table1 A
FULL JOIN table2 B
ON A.placementid = B.placementid
AND A.campaignid = B.campaignid
AND A.date = B.date
LEFT JOIN (SELECT Count(A.placementid) AS Placement_Count,
placementid. campaignid,
date
FROM table1
GROUP BY placementid,
campaignid,
date) c
ON A.placementid = C.placementid
AND A.campaignid = C.campaignid
AND A.date = C.date
GROUP BY A.placementid,
A.campaignid,
A.date
I am dividing Cost by placement because in source the cost was allocated for one placement only and one time so I have to divide those because in actual table the same Placementid repeat more than 1 times on same date.
As you didn't provide any expected output I guessing here but if the result you want is this:
PlacementID CampaignID Date Impressions Cost
----------- ----------- ----------------------- ----------- -----------
100 10 2014-04-01 02:00:00.000 1000 5000
100 11 2014-04-01 02:00:00.000 500 7000
101 10 2014-04-01 02:00:00.000 1500 6000
103 10 2014-04-01 02:00:00.000 NULL 8000
Then the following query should do it:
SELECT COALESCE(A.PlacementID,b.placementid) AS PlacementID,
COALESCE(A.campaignid, b.campaignid) AS CampaignID,
COALESCE(A.date, b.date) AS [Date],
SUM(A.impressions) AS Impressions,
SUM(CASE
WHEN C.placement_count > 1 THEN ( B.cost / C.placement_count )
ELSE B.cost
END ) AS Cost
FROM table1 A
FULL JOIN table2 B
ON A.[PlacementID] = B.placementid
AND A.campaignid = B.campaignid
AND A.date = B.date
LEFT JOIN (SELECT COUNT(PlacementID) AS Placement_Count,
placementid, campaignid,
date
FROM table1
GROUP BY placementid,
campaignid,
date) c
ON A.[PlacementID] = C.placementid
AND A.campaignid = C.campaignid
AND A.date = C.date
GROUP BY COALESCE(A.PlacementID, B.PlacementID),
COALESCE(A.campaignid, b.campaignid),
COALESCE(A.date, b.date)
Sample SQL Fiddle
I have two tables, one with transactions (with date). The other with a percentage and date the percentage it went into effect (assume 00:00:00). The percentage remains in effect until a new percent goes into effect. I need to join on the percentage that was in effect when the transaction happened.
transactions_table
event_date amount
2011-01-01 230
2011-02-18 194
2011-03-22 56
2011-04-30 874
percent_table
effective percent
2010-12-30 15
2011-03-05 25
2011-04-12 30
The result I'm looking for is:
event_date amount percent
2011-01-01 230 15
2011-02-18 194 15
2011-03-22 56 25
2011-04-30 874 30
I've tried:
SELECT t.event_date, t.amount, p.percent
FROM transactions_table AS t
LEFT JOIN percent_table AS p ON t.event_date >= p.effective
ORDER BY `t`.`event_date` DESC LIMIT 0 , 30;
That gives me, seemingly random percentages. It seems to me like I need to get the greatest date >= p.effective, not just any random date >= p.effective.
I tried:
SELECT t.event_date, p.percent
FROM bedic_sixsummits_transactions AS t
LEFT JOIN bedic_sixsummits_percent AS p ON MAX(t.event_date >= p.effective)
ORDER BY `t`.`event_date` DESC LIMIT 0 , 30
but MySQL just laughed at my feeble attempt.
How can I do this?
SELECT t.event_date, t.amount, p.percent
FROM bedic_sixsummits_transactions AS t
LEFT JOIN bedic_sixsummits_percent AS p
ON p.effective =
( SELECT MAX( p2.effective ) FROM bedic_sixsummits_percent AS p2
WHERE p2.effective <= t.event_date
)
ORDER BY t.event_date DESC LIMIT 0 , 30
Even more simpler and with no subquery:
SELECT event_date, amount, MAX(_percent) as _percent
FROM transactions_table
LEFT JOIN percent_table p1 ON event_date >= effective
GROUP BY event_date, amount
ORDER BY event_date;
http://sqlfiddle.com/#!3/e8ca3/17/0
Note that it is possible because of the business model involved. If you wan't to retrieve other fields of the percent_table it won't be appropriate anymore :/