sql - على - كيفية ربط الجداول في phpmyadmin




جلب الصف الذي يحتوي على أقصى قيمة لعمود (20)

(T-SQL) أولا الحصول على جميع المستخدمين و maxdate بهم. انضم إلى الجدول للعثور على القيم المقابلة للمستخدمين على maxdates.

create table users (userid int , value int , date datetime)
insert into users values (1, 1, '20010101')
insert into users values (1, 2, '20020101')
insert into users values (2, 1, '20010101')
insert into users values (2, 3, '20030101')

select T1.userid, T1.value, T1.date 
    from users T1,
    (select max(date) as maxdate, userid from users group by userid) T2    
    where T1.userid= T2.userid and T1.date = T2.maxdate

النتائج:

userid      value       date                                    
----------- ----------- -------------------------- 
2           3           2003-01-01 00:00:00.000
1           2           2002-01-01 00:00:00.000

الطاولة:

UserId, Value, Date.

أريد الحصول على UserId وقيمة الحد الأقصى (تاريخ) لكل UserId. بمعنى ، القيمة لكل UserId يحتوي على أحدث تاريخ. هل هناك طريقة للقيام بذلك ببساطة في SQL؟ (يفضل أوراكل)

تحديث: اعتذار عن أي غموض: أنا بحاجة للحصول على جميع UserIds. ولكن بالنسبة لكل UserId ، يكون ذلك الصف فقط حيث يحتفظ هذا المستخدم بأحدث تاريخ.


أرى العديد من الأشخاص يستخدمون الاستعلامات الفرعية أو غيرها من الميزات الخاصة بالمورد للقيام بذلك ، ولكن غالباً ما أقوم بهذا النوع من الاستعلام بدون استعلامات فرعية بالطريقة التالية. ويستخدم SQL عادي وسريع لذلك يجب أن يعمل في أي ماركة من RDBMS.

SELECT t1.*
FROM mytable t1
  LEFT OUTER JOIN mytable t2
    ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;

بمعنى آخر: أحضر الصف من t1 حيث لا يوجد صف آخر بنفس UserId وتاريخ أكبر.

(أضع معرف "التاريخ" في المحددات لأنها كلمة محجوزة في SQL.)

في حالة إذا t1."Date" = t2."Date" ، يظهر مضاعفة. عادة ما يكون للجداول مفتاح auto_inc(seq) ، مثل id . لتجنب مضاعفة يمكن استخدامها:

SELECT t1.*
FROM mytable t1
  LEFT OUTER JOIN mytable t2
    ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date") 
         OR (t1."Date" = t2."Date" AND t1.id < t2.id))
WHERE t2.UserId IS NULL;

رد منFarhan:

فيما يلي شرح أكثر تفصيلاً:

يحاول صلة خارجية الانضمام t1 مع t2. بشكل افتراضي ، يتم إرجاع كافة نتائج t1 ، وإذا كان هناك تطابق في t2 ، يتم إرجاع أيضاً. إذا لم يكن هناك تطابق في t2 لصف معين من t1 ، فسيستمر الاستعلام في إرجاع صف t1 ، ويستخدم NULL كعنصر نائب لكافة أعمدة t2. هذا هو مجرد كيفية عمل الصلات الخارجي بشكل عام.

الخدعة في هذا الاستعلام هي لتصميم حالة مطابقة الصلة بحيث يجب أن يطابق t2 نفس userid ، وتاريخ أكبر . تكون الفكرة إذا كان هناك صف في t2 له تاريخ أعظم ، فإن الصف في t1 هو مقارنة لا يمكن أن يكون أكبر موعد لذلك userid. ولكن إذا لم يكن هناك تطابق - على سبيل المثال ، إذا لم يوجد صف في t2 مع تاريخ أكبر من الصف في t1 - فنحن نعرف أن الصف في t1 هو الصف الذي له أكبر تاريخ لمستخدم معين.

في هذه الحالات (عند عدم وجود تطابق) ، ستكون أعمدة t2 فارغة - حتى الأعمدة المحددة في شرط الربط. ولهذا السبب نستخدم WHERE t2.UserId IS NULL ، لأننا نبحث عن الحالات التي لم يتم فيها العثور على أي صف بتاريخ أكبر لمستخدم معين.


أعلم أنك طلبت Oracle ، ولكن في SQL 2005 نستخدم الآن هذا:


-- Single Value
;WITH ByDate
AS (
SELECT UserId, Value, ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY Date DESC) RowNum
FROM UserDates
)
SELECT UserId, Value
FROM ByDate
WHERE RowNum = 1

-- Multiple values where dates match
;WITH ByDate
AS (
SELECT UserId, Value, RANK() OVER (PARTITION BY UserId ORDER BY Date DESC) Rnk
FROM UserDates
)
SELECT UserId, Value
FROM ByDate
WHERE Rnk = 1

ألن يكون شرط QUALIFY أبسط وأفضل؟

select userid, my_date, ...
from users
qualify rank() over (partition by userid order by my_date desc) = 1

للسياق ، على Teradata هنا اختبار حجم لائق من هذا يعمل في 17S مع هذا الإصدار QUALIFY وفي 23S مع الحل "inline view '/ Aldridge # 1.


إذا كان (UserID، Date) فريدًا ، فلن يظهر أي تاريخ مرتين لنفس المستخدم ، ثم:

select TheTable.UserID, TheTable.Value
from TheTable inner join (select UserID, max([Date]) MaxDate
                          from TheTable
                          group by UserID) UserMaxDate
     on TheTable.UserID = UserMaxDate.UserID
        TheTable.[Date] = UserMaxDate.MaxDate;

إذا كنت تستخدم Postgres ، فيمكنك استخدام array_agg مثل

SELECT userid,MAX(adate),(array_agg(value ORDER BY adate DESC))[1] as value
FROM YOURTABLE
GROUP BY userid

لست على دراية بـ Oracle. هذا هو ما خطرت لي

SELECT 
  userid,
  MAX(adate),
  SUBSTR(
    (LISTAGG(value, ',') WITHIN GROUP (ORDER BY adate DESC)),
    0,
    INSTR((LISTAGG(value, ',') WITHIN GROUP (ORDER BY adate DESC)), ',')-1
  ) as value 
FROM YOURTABLE
GROUP BY userid 

كلا الاستعلامات ترجع نفس النتائج كإجابة مقبولة. انظر SQLFiddles:

  1. إجابة مقبولة
  2. حل بلدي مع بوستجرس
  3. حل بلدي مع أوراكل


باستخدام PostgreSQL 9 ، يمكنك استخدام هذا:

select user_id, user_value_1, user_value_2
  from (select user_id, user_value_1, user_value_2, row_number()
          over (partition by user_id order by user_date desc) 
        from users) as r
  where r.row_number=1

حاول أولاً أن أخطئ في قراءة السؤال ، باتباع أعلى إجابة ، وهنا مثال كامل مع النتائج الصحيحة:

CREATE TABLE table_name (id int, the_value varchar(2), the_date datetime);

INSERT INTO table_name (id,the_value,the_date) VALUES(1 ,'a','1/1/2000');
INSERT INTO table_name (id,the_value,the_date) VALUES(1 ,'b','2/2/2002');
INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'c','1/1/2000');
INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'d','3/3/2003');
INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'e','3/3/2003');

-

  select id, the_value
      from table_name u1
      where the_date = (select max(the_date)
                     from table_name u2
                     where u1.id = u2.id)

-

id          the_value
----------- ---------
2           d
2           e
1           b

(3 row(s) affected)

سيؤدي ذلك إلى استرداد كافة الصفوف التي تساوي قيمة العمود my_date لها الحد الأقصى لقيمة my_date لذلك userid. هذا قد استرداد صفوف متعددة من أجل userid حيث يكون الحد الأقصى للتاريخ على صفوف متعددة.

select userid,
       my_date,
       ...
from
(
select userid,
       my_Date,
       ...
       max(my_date) over (partition by userid) max_my_date
from   users
)
where my_date = max_my_date

"وظائف تحليلية روك"

تحرير: فيما يتعلق بالتعليق الأول ...

"استخدام الاستعلامات التحليلية والانضمام إلى الذات يهزم غرض الاستفسارات التحليلية"

لا يوجد ارتباط ذاتي في هذا الرمز. هناك بدلاً من ذلك دالة تقييم تم وضعها على نتيجة العرض المضمن الذي يحتوي على الوظيفة التحليلية - وهي مسألة مختلفة جدًا وممارسة قياسية تمامًا.

"الإطار الافتراضي في Oracle هو من الصف الأول في القسم إلى المجلد الحالي"

لا ينطبق بند الشباك إلا في حالة وجود أمر بموجب شرط. مع عدم وجود ترتيب بواسطة شرط ، لا يتم تطبيق أي شرط للشباك بشكل افتراضي ولا يمكن تحديد أي منهما بشكل واضح.

يعمل الرمز.


فقط اختبار هذا ويبدو أنه يعمل على جدول تسجيل

select ColumnNames, max(DateColumn) from log  group by ColumnNames order by 1 desc

فقط كان لا بد من كتابة مثال "العيش" في العمل :)

هذا واحد يدعم قيم متعددة لـ UserId في نفس التاريخ.

الأعمدة: UserId ، القيمة ، التاريخ

SELECT
   DISTINCT UserId,
   MAX(Date) OVER (PARTITION BY UserId ORDER BY Date DESC),
   MAX(Values) OVER (PARTITION BY UserId ORDER BY Date DESC)
FROM
(
   SELECT UserId, Date, SUM(Value) As Values
   FROM <<table_name>>
   GROUP BY UserId, Date
)

يمكنك استخدام FIRST_VALUE بدلاً من MAX والبحث عنها في خطة التوضيح. لم يكن لدي الوقت للعب معها.

وبالطبع ، إذا كنت تبحث عن جداول ضخمة ، فمن الأفضل أن تستخدم تلميحات كاملة في استفسارك.


لا أعرف أسماء أعمدةك بالضبط ، ولكنها ستكون شيئًا كالتالي:

    select userid, value
      from users u1
     where date = (select max(date)
                     from users u2
                    where u1.userid = u2.userid)

لا أكون في العمل ، ليس لدي أوراكل لتسليمها ، ولكن يبدو أنني أذكر أن أوراكل تسمح بتطابق أعمدة متعددة في جملة IN ، والتي يجب على الأقل تجنب الخيارات التي تستخدم طلب البحث الفرعي المرتبط ، والذي نادراً ما يكون جيدًا فكرة.

شيء من هذا القبيل ، ربما (لا أتذكر إذا كانت قائمة الأعمدة يجب أن تكون بين قوسين أو لا):

SELECT * 
FROM MyTable
WHERE (User, Date) IN
  ( SELECT User, MAX(Date) FROM MyTable GROUP BY User)

تحرير: حاول فقط لريال مدريد:

SQL> create table MyTable (usr char(1), dt date);
SQL> insert into mytable values ('A','01-JAN-2009');
SQL> insert into mytable values ('B','01-JAN-2009');
SQL> insert into mytable values ('A', '31-DEC-2008');
SQL> insert into mytable values ('B', '31-DEC-2008');
SQL> select usr, dt from mytable
  2  where (usr, dt) in 
  3  ( select usr, max(dt) from mytable group by usr)
  4  /

U DT
- ---------
A 01-JAN-09
B 01-JAN-09

لذا ، فإنه يعمل ، على الرغم من أن بعض الأشياء الجديدة المخيفة التي تم ذكرها في مكان آخر قد تكون أكثر فاعلية.


ما قمت به shuold جعل هذا البديل للاستعلام السابق:

SELECT UserId, Value FROM Users U1 WHERE 
Date = ( SELECT MAX(Date)    FROM Users where UserId = U1.UserId)

وأعتقد أن هذا يجب أن تعمل؟

Select
T1.UserId,
(Select Top 1 T2.Value From Table T2 Where T2.UserId = T1.UserId Order By Date Desc) As 'Value'
From
Table T1
Group By
T1.UserId
Order By
T1.UserId

يفترض أن يكون تاريخ فريدة بالنسبة لـ UserID معين ، وهنا بعض TSQL:

SELECT 
    UserTest.UserID, UserTest.Value
FROM UserTest
INNER JOIN
(
    SELECT UserID, MAX(Date) MaxDate
    FROM UserTest
    GROUP BY UserID
) Dates
ON UserTest.UserID = Dates.UserID
AND UserTest.Date = Dates.MaxDate 

SELECT userid, MAX(value) KEEP (DENSE_RANK FIRST ORDER BY date DESC)
  FROM table
  GROUP BY userid

select   UserId,max(Date) over (partition by UserId) value from users;

select VALUE from TABLE1 where TIME = 
   (select max(TIME) from TABLE1 where DATE= 
   (select max(DATE) from TABLE1 where CRITERIA=CRITERIA))




greatest-n-per-group