Нужна помощь для написания сложного запроса SQL - PullRequest
0 голосов
/ 31 августа 2018

Мне нужна помощь со сложным запросом SQL. Вот мои настройки: у меня есть две таблицы USER_TABLE и USER_VISIT_STAT. USER_TABLE имеют такие столбцы, как ID,USER_NAME,UID,DEPARTMENT и USER_VISIT_STAT имеют такие столбцы, как ID,USERID,LAST_VISIT_DATE. Поле USERID таблицы USER_VISIT_STAT содержит USER_TABLE.ID.

Когда пользователь входит в приложение, его текущая дата сохраняется в таблице USER_VISIT_STAT (см. Скриншот). Поэтому мне нужно получить информацию о пользователе, который не подключен к приложению с последних 2 лет. Но мы должны позаботиться о UID. (означает, что вы можете видеть в USER_TABLE есть две записи с одинаковым UID, но регистр отличается. В USER_VISIT_STAT вы можете видеть, что 101 LAST_VISIT_DATE равен 31-08-18, а 103 LAST_VISIT_DATE равен 20-01-16. Таким образом, вы должны игнорировать оба идентификатора, потому что пользователь один и тот же). В таблице ответов мне нужно указать имя пользователя, идентификатор пользователя, отдел пользователя и максимальное количество пользователей (последняя активная дата).

+--------------------------------------+
|             USER_TABLE               |
+--------------------------------------+
| ID    | NAME    | UID   | DEPARTMENT |
+--------------------------------------+
| 101   | PRAKASH | US45  | ENGG       |
| 102   | RAJESH  | US22  | ENGG       |
| 103   | PRAKASH | us45  | HR         |
| 104   | HARI    |  US9  | ENGG       |
| 105   | MAYANK  | US90  | HR         |
+--------------------------------------+
+--------------------------------+
|          USER_VISIT_STAT       |
+--------------------------------+
| ID | USID | MAX(LAST_VISIT_DATE)|
+--------------------------------+
| 1  | 101 |    31-08-18         |
| 2  | 102 |    30-08-18         |
| 3  | 101 |    30-08-18         |
| 4  | 103 |    20-01-16         |
| 5  | 104 |    29-08-16         |
| 6  | 105 |    19-07-16         |
| 7  | 101 |    12-06-16         |
| 8  | 102 |    12-06-16         |
| 9  | 104 |    13-04-16         |
+--------------------------------+
+-------------------------------------------------+
|                    RESPONSE                     |
+-------------------------------------------------+
| NAME   | UID  |   DEPARTMENT | LAST_VISIT_DATE  |
+-------------------------------------------------+
| HARI   | US9  |   ENGG       |    29-08-16      |
| MAYANK | US09 |   HR         |  19-07-16        |
+-------------------------------------------------+

Ответы [ 5 ]

0 голосов
/ 04 сентября 2018

Используя аналитическую форму функции MAX (), разделение, которое в верхнем регистре UID решит это. Доступен в качестве демонстрации здесь SQL Fiddle

Запрос 1 :

SELECT
  M.LAST_VISIT_DATE, U.*
FROM (
    SELECT
      U."UID" 
    , V.LAST_VISIT_DATE
    , MAX(V.LAST_VISIT_DATE) OVER(PARTITION BY UPPER(U."UID")) MAX_VISIT
    FROM USER_TABLE U
    INNER JOIN USER_VISIT_STAT V ON U.ID = V.USID
    ) M
INNER JOIN USER_TABLE U ON M."UID" = U."UID"
WHERE M.MAX_VISIT < ADD_MONTHS(SYSDATE,-24)
AND M.LAST_VISIT_DATE = M.MAX_VISIT

Результаты :

|       LAST_VISIT_DATE |  ID |   NAME |  UID | DEPARTMENT |
|-----------------------|-----|--------|------|------------|
| 2016-08-29 00:00:00.0 | 104 |   HARI |  US9 |       ENGG |
| 2016-07-19 00:00:00.0 | 105 | MAYANK | US90 |         HR |

Настройка схемы Oracle 11g R2 :

CREATE TABLE USER_TABLE
    ("ID" int, "NAME" varchar2(7), "UID" varchar2(4), "DEPARTMENT" varchar2(4))
;

INSERT ALL
    INTO USER_TABLE ("ID", "NAME", "UID", "DEPARTMENT")
         VALUES (101, 'PRAKASH', 'US45', 'ENGG')
    INTO USER_TABLE ("ID", "NAME", "UID", "DEPARTMENT")
         VALUES (102, 'RAJESH', 'US22', 'ENGG')
    INTO USER_TABLE ("ID", "NAME", "UID", "DEPARTMENT")
         VALUES (103, 'PRAKASH', 'us45', 'HR')
    INTO USER_TABLE ("ID", "NAME", "UID", "DEPARTMENT")
         VALUES (104, 'HARI', 'US9', 'ENGG')
    INTO USER_TABLE ("ID", "NAME", "UID", "DEPARTMENT")
         VALUES (105, 'MAYANK', 'US90', 'HR')
SELECT * FROM dual
;

CREATE TABLE USER_VISIT_STAT       
    ("ID" int, "USID" int, "LAST_VISIT_DATE" timestamp)
;

INSERT ALL 
    INTO USER_VISIT_STAT        ("ID", "USID", "LAST_VISIT_DATE")
         VALUES (1, 101, '31-Aug-2018 12:00:00 AM')
    INTO USER_VISIT_STAT        ("ID", "USID", "LAST_VISIT_DATE")
         VALUES (2, 102, '30-Aug-2018 12:00:00 AM')
    INTO USER_VISIT_STAT        ("ID", "USID", "LAST_VISIT_DATE")
         VALUES (3, 101, '30-Aug-2018 12:00:00 AM')
    INTO USER_VISIT_STAT        ("ID", "USID", "LAST_VISIT_DATE")
         VALUES (4, 103, '20-Feb-2016 12:00:00 AM')
    INTO USER_VISIT_STAT        ("ID", "USID", "LAST_VISIT_DATE")
         VALUES (5, 104, '29-Aug-2016 12:00:00 AM')
    INTO USER_VISIT_STAT        ("ID", "USID", "LAST_VISIT_DATE")
         VALUES (6, 105, '19-Jul-2016 12:00:00 AM')
    INTO USER_VISIT_STAT        ("ID", "USID", "LAST_VISIT_DATE")
         VALUES (7, 101, '12-Jun-2016 12:00:00 AM')
    INTO USER_VISIT_STAT        ("ID", "USID", "LAST_VISIT_DATE")
         VALUES (8, 102, '12-Jun-2016 12:00:00 AM')
    INTO USER_VISIT_STAT        ("ID", "USID", "LAST_VISIT_DATE")
         VALUES (9, 104, '13-Apr-2016 12:00:00 AM')
SELECT * FROM dual
;
0 голосов
/ 31 августа 2018

Что-то вроде

select uid,name,department,last_visit_date
from (
  select 
    a.id id, max(a.id) over (partition by a.uid) maxid,
    a.uid uid,a.name name,a.department department,
    max(last_visit_date) over (partition by a.uid) last_visit_date
  from 
    user_table a, user_visit_stat b
  where 
    a.id=b.uid
)
where last_visit_date<=add_years(sysdate,-2) and a.id=maxid
0 голосов
/ 31 августа 2018

Попробуйте ниже:

select a.uid,a.name,b.department,a.id,lastvisit
from
(select uid,name,max(id) as id
from USER_TABLE group by uid,name)a
inner join USER_TABLE b on a.uid=b.uid
inner join
(select uid,max(LAST_VISIT_DATE) as lastvisit
group by uid having max(LAST_VISIT_DATE)< trunc(sysdate, 'yyyy') - interval '2' year)x
on a.id=x.id
0 голосов
/ 31 августа 2018

используйте агрегатную функцию и присоединяйтесь

  select u.*,t.last_visit from     
    (
   select min(ID) as ID ,Name, UPPER(UID) as UID,DEPARTMENT from USER_TABLE
    group by Name, UPPER(UID),DEPARTMENT
    ) as u 
    join
    (
    select UID,max(LAST_VISIT_DATE) as last_visit from USER_VISIT_STAT us
    group by UID 
    having max(LAST_VISIT_DATE) between  add_months(sysdate,-26) and add_months(sysdate,-24)
    ) as t
    on u.ID=t.UID

Из разговора мне кажется, что вам нужно ниже

select u.*, x.last_visit from
       (
       select Name, UPPER(UID) as UID,DEPARTMENT from USER_TABLE
        group by Name, UPPER(UID),DEPARTMENT
        ) as u 

        join
        (   
        select a.name,a.last_visit from
        (
        select distinct iu.NAME,last_visit from
        (
        select USID,max(LAST_VISIT_DATE) as last_visit from USER_VISIT_STAT us
        group by USID 
        having max(LAST_VISIT_DATE) between  add_months(sysdate,-26) and add_months(sysdate,-24)
        ) as t1 
        join
        USER_TABLE as iu on t1.USID=iu.ID
        ) a left join           

        (
        select distinct iu.NAME,    
        (
        select USID  from USER_VISIT_STAT us
        group by USID 
        having min(LAST_VISIT_DATE) between  add_months(sysdate,-23) and add_months(sysdate,0)
        ) as t1 
        join
        USER_TABLE as iu on t1.UID=iu.ID    
        ) b on a.NAME=b.NAME
        where b.NAME is null 
        ) x on u.Name=x.Name
0 голосов
/ 31 августа 2018

Я бы использовал row_number, чтобы получить последние данные о пользователе за uid, присоединить их к дате последнего посещения за uid и отфильтровать по этому:

SELECT name, u.uid, department, max_visit
FROM   (SELECT name,
               uid,
               department,
               ROW_NUMBER() OVER (PARTITION BY uid ORDER BY id DESC) AS rn
        FROM   user_table) u
JOIN   (SELECT   uid, MAX(last_visit_date) AS max_visit
        FROM     user_visit_stat
        GROUP BY uid
        HAVING   MONTHS_BETWEEN(sysdate, MAX(last_visit_date)) >= 24) us ON u.uid = us.uid
WHERE  rn = 1              
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...