Как добавить Лимит запроса в подзапросе mysql - PullRequest
0 голосов
/ 11 декабря 2018
SELECT kodeagent
 , IFNULL((
   SELECT COUNT(1)
   FROM bsn_data
   WHERE bsn_data.periode LIKE '2018-12-%%'
   AND bsn_data.kodeupline2 = bsn_kode_agent.kodeagent
   AND bsn_data.kodeagent IN(
       SELECT bsn_data.kodeagent
       FROM bsn_data
       WHERE bsn_data.periode LIKE '2018-12-%%'
       AND bsn_data.kodeupline2 = bsn_kode_agent.kodeagent
       GROUP BY bsn_data.kodeagent ORDER BY COUNT(1) DESC LIMIT 1
       )
   ), 0) AS totps
FROM bsn_kode_agent
WHERE fungsi = 'sales agent'
ORDER BY totps DESC

Получение результата

Эта версия MariaDB еще не поддерживает 'LIMIT & IN / ALL / ANY / SOME subquery'

Как мне решить эту проблему?Я хочу добавить запрос лимита в подзапросе .. спасибо ..

Ответы [ 4 ]

0 голосов
/ 12 декабря 2018

MariaDB предлагает «оконные функции», которые можно использовать для этого, я полагаю (также ссылаясь на предыдущий вопрос, который, кажется, требует только подсчета от «трех лучших» агентов):

CREATE TABLE bsn_kode_agent(
   kodeagent VARCHAR(10) NOT NULL PRIMARY KEY
  ,fungsi    VARCHAR(40) NOT NULL
);
INSERT INTO bsn_kode_agent(kodeagent,fungsi) 
  VALUES
  ('a','sales agent')
, ('b','sales agent');
CREATE TABLE bsn_data(
   kodeagent   VARCHAR(1) NOT NULL
  ,kodeupline2 VARCHAR(2) NOT NULL
  ,periode     DATE  NOT NULL
);
INSERT INTO bsn_data(kodeagent,kodeupline2,periode) 
VALUES 
  ('a','b1','2018-12-01')
, ('a','b1','2018-12-01')
, ('a','b1','2018-12-01')
, ('a','c1','2018-12-01')
, ('a','c1','2018-12-01')
, ('a','c1','2018-12-01')
, ('a','d1','2018-12-01')
, ('a','d1','2018-12-01')
, ('a','e1','2018-12-01')
, ('a','f1','2018-12-01')
;
SELECT
    b.kodeagent
  , IFNULL( SUM( d.total ), 0 )  AS totps
FROM bsn_kode_agent AS b
LEFT JOIN (
        SELECT
            tableb.kodeupline2
          , tableb.kodeagent
          , tableb.total
          , ROW_NUMBER() OVER (PARTITION BY tableb.kodeagent
                                 ORDER BY tableb.total DESC) as rn
        FROM (
            SELECT
                bsn_data.kodeupline2
              , bsn_data.kodeagent
              , COUNT( 1 ) total
            FROM bsn_data
            WHERE  bsn_data.periode >= '2018-12-01'
              AND  bsn_data.periode <  '2018-12-01' + INTERVAL 1 MONTH
            GROUP BY
                bsn_data.kodeupline2
              , bsn_data.kodeagent
        ) AS tableb
    ) d ON d.kodeagent = b.kodeagent and d.rn <=3 
WHERE b.fungsi = 'sales agent'
group by
    b.kodeagent
ORDER BY
    totps DESC
kodeagent | totps
:-------- | ----:
a         |     8
b         |     0

Ниже: Результат подзапроса, еслизапустить автономно.Обратите внимание, что в столбце rn возможна последующая фильтрация только агентов с наибольшим числом.

         SELECT
            tableb.kodeupline2
          , tableb.kodeagent
          , tableb.total
          , ROW_NUMBER() OVER (PARTITION BY tableb.kodeagent
                                 ORDER BY tableb.total DESC) as rn
        FROM (
            SELECT
                bsn_data.kodeupline2
              , bsn_data.kodeagent
              , COUNT( 1 ) total
            FROM bsn_data
            WHERE  bsn_data.periode >= '2018-12-01'
              AND  bsn_data.periode <  '2018-12-01' + INTERVAL 1 MONTH
            GROUP BY
                bsn_data.kodeupline2
              , bsn_data.kodeagent
        ) AS tableb
kodeupline2 | kodeagent | total | rn
:---------- | :-------- | ----: | -:
b1          | a         |     3 |  1
c1          | a         |     3 |  2
d1          | a         |     2 |  3
e1          | a         |     1 |  4
f1          | a         |     1 |  5

db <> fiddle здесь

Обратите также внимание на то, насколько полезно иметь некоторые данные выборки, НО , поскольку этого не было. Возможно, я сделал неверные предположения относительно образца, показанного здесь - этоВСЕГДА лучше, если данные для примера поставляются с вопросом.

0 голосов
/ 11 декабря 2018

Я думаю, что это будет работать:

SELECT ka.kodeagent
       (SELECT COUNT(1)
        FROM bsn_data d
        WHERE d.periode >= '2018-12-01' AND
              d.periode < '2019-01-01' AND
              d.kodeupline2 = ka.kodeagent AND
              d.kodeagent = (SELECT d2.kodeagent
                             FROM bsn_data d2
                                  d2.periode >= '2018-12-01' AND
                                  d2.periode < '2019-01-01' AND
                                  d2.kodeupline2 = ka.kodeagent
                             GROUP BY d2.kodeagent
                             ORDER BY COUNT(1) DESC
                             LIMIT 1
                            )
        ) AS totps
FROM bsn_kode_agent ka
WHERE ka.fungsi = 'sales agent'
ORDER BY totps DESC;

Примечания:

  • Не используйте строковые операции с датами!Используйте правильные операции с датой.
  • Используйте псевдонимы таблиц и уточните имена таблиц.
  • = можно использовать limit, хотя in нельзя.
  • COUNT()не возвращает NULL, поэтому нет необходимости в NULL сравнении.

Я все еще не думаю, что запрос будет работать, потому что у вас есть дважды вложенное предложение корреляции.Но это решает вашу непосредственную проблему.

Если это все еще не работает, задайте еще один вопрос, предоставьте образцы данных, желаемые результаты и объяснение логики, которую вы пытаетесь реализовать..

0 голосов
/ 11 декабря 2018

Избегать IN ( SELECT ... )

В этом случае должно быть легко превратить его в JOIN.

Изменить средний запрос:

SELECT  COUNT(1)
    FROM  bsn_data
    WHERE  bsn_data.periode LIKE '2018-12-%%'
      AND  bsn_data.kodeupline2 = bsn_kode_agent.kodeagent
      AND  bsn_data.kodeagent IN (
        SELECT  bsn_data.kodeagent
            FROM  bsn_data
            WHERE  bsn_data.periode LIKE '2018-12-%%'
              AND  bsn_data.kodeupline2 = bsn_kode_agent.kodeagent
            GROUP BY  bsn_data.kodeagent
            ORDER BY  COUNT(1) DESC
            LIMIT  1 
                          )

на

SELECT  COUNT(1)
    FROM  
        ( SELECT  bsn_data.kodeagent
            FROM  bsn_data
            WHERE  bsn_data.periode >= '2018-12-01'
              AND  bsn_data.periode  < '2018-12-01' + INTERVAL 1 MONTH
              AND  bsn_data.kodeupline2 = bsn_kode_agent.kodeagent
            GROUP BY  bsn_data.kodeagent
            ORDER BY  COUNT(1) DESC
            LIMIT  1 
        ) AS x
    JOIN  bsn_data  ON x.kodeagent = bsn_data.kodeagent
    WHERE  bsn_data.periode >= '2018-12-01'
      AND  bsn_data.periode  < '2018-12-01' + INTERVAL 1 MONTH
      AND  bsn_data.kodeupline2 = bsn_kode_agent.kodeagent

Индексы:

bsn_data:  INDEX(kodeupline2, periode, kodeagent)  -- in this order
bsn_data:  (kodeagent)  -- is this the PRIMARY KEY?

Но подождите!Разве это не может быть упрощено до

SELECT  COUNT(1) AS ct
    FROM  bsn_data
    WHERE  bsn_data.periode >= '2018-12-01'
      AND  bsn_data.periode <  '2018-12-01' + INTERVAL 1 MONTH
      AND  bsn_data.kodeupline2 = bsn_kode_agent.kodeagent
    GROUP BY  bsn_data.kodeagent
    ORDER BY  COUNT(1) DESC
    LIMIT  1 
0 голосов
/ 11 декабря 2018

Не нужно ничего проверять мой ответ.Пожалуйста, попробуйте это, оберните подзапрос в пыльник, чтобы получить псевдоним таблицы tmp (tmp_bsn_data):

SELECT kodeagent
 , IFNULL((
   SELECT COUNT(1)
   FROM bsn_data
   WHERE bsn_data.periode LIKE '2018-12-%%'
   AND bsn_data.kodeupline2 = bsn_kode_agent.kodeagent
   AND bsn_data.kodeagent IN( select tmp_bsn_data.kodeagent from (
       SELECT bsn_data.kodeagent
       FROM bsn_data
       WHERE bsn_data.periode LIKE '2018-12-%%'
       AND bsn_data.kodeupline2 = bsn_kode_agent.kodeagent
       GROUP BY bsn_data.kodeagent ORDER BY COUNT(1) DESC LIMIT 1
       ) tmp_bsn_data
       )
   ), 0) AS totps
FROM bsn_kode_agent
WHERE fungsi = 'sales agent'
ORDER BY totps DESC
...