问题
Given below are the results of my query. But there are many redundant records, therefore, I want to filter out the results of this query. My goal is to extract only two records per angle, first and the last. For example when the angle is 195, I want to get its first record when the date=2/27/2017, time=2:00:00 AM and the second record when the date is 2/27/2017 and time=9:00:00 AM. Similarly when the angle is changed to 210 I want to get its first record when the date=2/27/2017 time=10:00:00 AM and the other record when the date and time is 2/27/2017 and 9:00:00 PM. And similarly for all the records. I tried to do it myself but it only returns one record per angle only the top one, dont know how do I get the last one. I am doing it using two queries, (Query1)
SELECT final.Date, final.Angle
FROM final
GROUP BY final.Date, final.Angle
and second query is (fileredOUtput)
SELECT Query1.Date, Query1.Angle, (SELECT TOP 1 final.Date FROM final WHERE Query1.Date=final.Date AND Query1.Angle= final.Angle)
AS NewDate,
(SELECT TOP 1 final.Angle FROM final WHERE Query1.Date=final.Date AND Query1.Angle= final.Angle) AS NewAngle,
(SELECT TOP 1 final.earthCol.Value FROM final WHERE Query1.Date=final.Date AND Query1.Angle= final.Angle) AS NewE_CV,
(SELECT TOP 1 final.earthCol.ColNu FROM final WHERE Query1.Date=final.Date AND Query1.Angle= final.Angle) AS New_E_CN,
(SELECT TOP 1 final.mars_Col.Value FROM final WHERE Query1.Date=final.Date AND Query1.Angle= final.Angle) AS NewM_CV,
(SELECT TOP 1 final.Col_apart FROM final WHERE Query1.Date=final.Date AND Query1.Angle= final.Angle) AS New_CApart,
(SELECT TOP 1 final.mars_Col.ColNu FROM final WHERE Query1.Date=final.Date AND Query1.Angle= final.Angle) AS NewM_CN,
(SELECT TOP 1 final.Time FROM final WHERE Query1.Date=final.Date AND Query1.Angle= final.Angle) AS NewTime
FROM Query1, final
WHERE (((Query1.Date) Between [Forms]![Query Form]![txtStartDate] And [Forms]![Query Form]![txtEndDate]));
Query results and results I need are marked with red. Looking forward to hear from you. Thank you.
回答1:
Try this
SELECT * FROM final INNER JOIN
(SELECT Min(DDate + DTime) AS DDateTime, Angle FROM final GROUP BY Angle
UNION SELECT Max(DDate + DTime) AS DDateTime, Angle FROM final GROUP BY Angle) mm
ON final.DDate + final.DTime = mm.DDateTime AND final.Angle = mm.Angle
Please note that in testing I changed the name of the first two columns to DDate and DTime respectively, because Date and Time are reserved words.
EDIT
That makes it considerably harder, particularly in Access which has no LEAD/LAG functions. The following should work, but someone might have a more elegant solution!
SELECT final.* FROM final INNER JOIN
(SELECT MIN(DDateTime) AS MDateTime, Angle FROM
(SELECT (f.DDate+ f.DTime) AS DDateTime, f.Earth_Value, f.Mars_Value, f.Earth_Col, f.Mars_Col, f.Diff, f.Angle, f.Col_Apart,
IIF(ISNULL((SELECT MIN(m.DDate + m.DTime) FROM final m where f.angle <> m.angle and (f.DDate+f.DTime) < (m.DDate+m.DTime))),
(SELECT MAX(DDate+DTime) FROM final),(SELECT MIN(m.DDate + m.DTime) FROM final m where f.angle <> m.angle and (f.DDate+f.DTime) < (m.DDate+m.DTime))) AS NextChangeDateTime
FROM final f order by DDate, DTime) g
GROUP BY g.Angle,g.NextChangeDateTime
UNION
SELECT MAX(DDateTime) AS MDateTime, Angle FROM
(SELECT (f.DDate+ f.DTime) AS DDateTime, f.Earth_Value, f.Mars_Value, f.Earth_Col, f.Mars_Col, f.Diff, f.Angle, f.Col_Apart,
IIF(ISNULL((SELECT MIN(m.DDate + m.DTime) FROM final m where f.angle <> m.angle and (f.DDate+f.DTime) < (m.DDate+m.DTime))),
(SELECT MAX(DDate+DTime) FROM final),(SELECT MIN(m.DDate + m.DTime) FROM final m where f.angle <> m.angle and (f.DDate+f.DTime) < (m.DDate+m.DTime))) AS NextChangeDateTime
FROM final f order by DDate, DTime) g
GROUP BY g.Angle,g.NextChangeDateTime) FLDates
ON final.DDate + final.DTime = FLDates.MDateTime
EDIT 2
Technically there is no such thing as a temporary table in MS Access. Really you just create a normal table and delete its contents every time you want to use it.
To create the table you need copy this into a Query Window (SQL View), and then click Run:
CREATE TABLE final (
DDate DATETIME NOT NULL,
DTime DATETIME NOT NULL,
Earth_Value DOUBLE NOT NULL,
Mars_Value DOUBLE NOT NULL,
Earth_Col INTEGER NOT NULL,
Mars_Col INTEGER NOT NULL,
Diff INTEGER NOT NULL);
Then before your existing Query type (you just need the first line):
INSERT into final
SELECT etc.
Now you will be able to run my query exactly as is.
回答2:
It could be:
SELECT
*
FROM
final,
(SELECT
final.Date, Min(final.Time) As MinTime, Max(final.Time) As MaxTime, final.Angle
FROM
final
GROUP BY
final.Date, final.Angle) As T
WHERE
final.Angle = T.Angle AND
final.Date = T.Date AND
((final.Time = T.MinTime) OR (final.Time = T.MaxTime))
ORDER BY
final.Date, final.Time, final.Angle
回答3:
Keep in mind that unless you also select the time from your table, you have no way of knowing which values you are retrieving. The date and angle in your required output isn't a unique combination.
You may need to modify slightly for Access
syntax.
SELECT
final.Date AS dt,
MIN(final.Time) AS tm,
final.Angle AS ag
FROM
final
GROUP BY
final.Date, final.Angle
UNION SELECT
final.Date,
MAX(final.Time),
final.Angle
FROM
final
GROUP BY
final.Date, final.Angle
ORDER BY
dt, ag, tm;
EDIT: SQL Fiddle example... http://sqlfiddle.com/#!9/2f638c/14
来源:https://stackoverflow.com/questions/45712200/how-can-i-get-selective-records-from-a-table-in-access