كيف يمكنني ضم الصف الأحدث في جدول إلى جدول آخر؟
-
20-08-2019 - |
سؤال
لدي بيانات تبدو كالتالي:
entities
id name
1 Apple
2 Orange
3 Banana
بشكل دوري، سيتم تشغيل العملية وإعطاء درجة لكل كيان.تقوم العملية بإنشاء البيانات وإضافتها إلى جدول النتائج كما يلي:
scores
id entity_id score date_added
1 1 10 1/2/09
2 2 10 1/2/09
3 1 15 1/3/09
4 2 10 1/03/09
5 1 15 1/4/09
6 2 15 1/4/09
7 3 22 1/4/09
أريد أن أكون قادرًا على تحديد جميع الكيانات بالإضافة إلى أحدث نتيجة مسجلة لكل منها مما يؤدي إلى بعض البيانات مثل هذه:
entities
id name score date_added
1 Apple 15 1/4/09
2 Orange 15 1/4/09
3 Banana 15 1/4/09
يمكنني الحصول على بيانات كيان واحد باستخدام هذا الاستعلام:
SELECT entities.*,
scores.score,
scores.date_added
FROM entities
INNER JOIN scores
ON entities.id = scores.entity_id
WHERE entities.id = ?
ORDER BY scores.date_added DESC
LIMIT 1
لكنني في حيرة من أمري بشأن كيفية اختيار نفس الشيء لجميع الكيانات.ربما يحدق في وجهي؟
شكرا جزيلا لأخذ الوقت.
شكرا على الردود العظيمة.سأعطي الأمر بضعة أيام لمعرفة ما إذا كان الحل المفضل سيظهر ثم سأختار الإجابة.
تحديث:لقد جربت العديد من الحلول المقترحة، والمشكلة الرئيسية التي أواجهها الآن هي أنه إذا لم يكن لدى الكيان بعد نتيجة تم إنشاؤها، فلن يظهر في القائمة.
كيف سيبدو SQL لضمان إرجاع جميع الكيانات، حتى لو لم يتم نشر أي نتيجة لها بعد؟
تحديث:تم تحديد الإجابة.شكرا لكم جميعا!
المحلول
وأفعل ذلك بهذه الطريقة:
SELECT e.*, s1.score, s1.date_added
FROM entities e
INNER JOIN scores s1
ON (e.id = s1.entity_id)
LEFT OUTER JOIN scores s2
ON (e.id = s2.entity_id AND s1.id < s2.id)
WHERE s2.id IS NULL;
نصائح أخرى
وفقط لإضافة تباين بلدي على ذلك:
SELECT e.*, s1.score
FROM entities e
INNER JOIN score s1 ON e.id = s1.entity_id
WHERE NOT EXISTS (
SELECT 1 FROM score s2 WHERE s2.id > s1.id
)
النهج 1
SELECT entities.*,
scores.score,
scores.date_added
FROM entities
INNER JOIN scores
ON entities.id = scores.entity_id
WHERE scores.date_added =
(SELECT max(date_added) FROM scores where entity_id = entities.id)
النهج 2
تكلفة الاستعلام بالنسبة للدُفعة:
SELECT entities.*,
scores.score,
scores.date_added
FROM entities
INNER JOIN scores
ON entities.id = scores.entity_id
inner join
(
SELECT
entity_id, max(date_added) as recent_date
FROM scores
group by entity_id
) as y on entities.id = y.entity_id and scores.date_added = y.recent_date
وأعرف أن هذا هو السؤال القديم، بس كنت أضيف نهجا وقد ذكر لا أحد حتى الآن، Cross Apply
أو Outer Apply
. هذه متوفرة في SQL Server 2005 (لم يتم وضع علامة على نوع قاعدة البيانات في هذا السؤال) أو أعلى
وباستخدام الجداول المؤقتة
DECLARE @Entities TABLE(Id INT PRIMARY KEY, name NVARCHAR(MAX))
INSERT INTO @Entities
VALUES (1, 'Apple'), (2, 'Orange'), (3, 'Banana'), (4, 'Cherry')
DECLARE @Scores TABLE(Id INT PRIMARY KEY, Entity_Id INT, Score INT, Date_Added DATE)
INSERT INTO @Scores
VALUES (1,1,10,'2009-02-01'),
(2,2,10,'2009-02-01'),
(3,1,15,'2009-02-01'),
(4,2,10,'2009-03-01'),
(5,1,15,'2009-04-01'),
(6,2,15,'2009-04-01'),
(7,3,22,'2009-04-01')
هل يمكن استخدام
SELECT E.Id, E.name, S.Score, S.Date_Added
FROM @Entities E
CROSS APPLY
(
SELECT TOP 1 *
FROM @Scores Sc
WHERE Sc.Entity_Id = E.Id
ORDER BY sc.Score DESC
) AS S
للحصول على النتائج المرجوة. وequivilent للسماح أن الكيانات دون عشرات يكون
SELECT E.Id, E.name, S.Score, S.Date_Added
FROM @Entities E
OUTER APPLY
(
SELECT TOP 1 *
FROM @Scores Sc
WHERE Sc.Entity_Id = E.Id
ORDER BY sc.Score DESC
) AS S
SELECT entities.*,
scores.score,
scores.date_added
FROM entities
INNER JOIN scores
ON entities.id = scores.entity_id
WHERE entities.id in
(select id from scores s2 where date_added = max(date_added) and s2.id = entities.id)
ORDER BY scores.date_added DESC
LIMIT 1
يمكنك أيضًا القيام بذلك اليوم في معظم أنظمة RDBMS (Oracle وPostgreSQL وSQL Server) باستخدام استعلام طبيعي باستخدام وظائف النافذة مثل ROW_NUMBER:
SELECT id, name, score, date_added FROM (
SELECT e.id, e.name, s.score, s.date_added,
ROW_NUMBER() OVER (PARTITION BY e.id ORDER BY s.date_added DESC) rn
FROM Entities e INNER JOIN Scores s ON e.id = s.entity_id
) tmp WHERE rn = 1;