MySQL over partition function subtitute [duplicate]

Вместо того, чтобы бросать код на вас, есть два понятия, которые являются ключом к пониманию того, как JS обрабатывает обратные вызовы и асинхронность. (это даже слово?)

Модель цикла события и параллелизма

Есть три вещи, о которых вам нужно знать; Очередь; цикл события и стек

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

while (queue.waitForMessage()) {
   queue.processNextMessage();
}

Как только он получает сообщение для запуска чего-то, он добавляет его в очередь. Очередь - это список вещей, которые ждут выполнения (например, ваш запрос AJAX). Представьте себе это так:

 1. call foo.com/api/bar using foobarFunc
 2. Go perform an infinite loop
 ... and so on

Когда одно из этих сообщений будет исполнено, оно выталкивает сообщение из очереди и создает стек, стек - это все, что нужно выполнить JS для выполнения инструкции в сообщение. Таким образом, в нашем примере ему говорят позвонить foobarFunc

function foobarFunc (var) {
  console.log(anotherFunction(var));
}

. Так что все, что foobarFunc должно выполнить (в нашем случае anotherFunction), будет вставлено в стек. исполняемый, а затем забытый - цикл события затем переместится на следующую вещь в очереди (или прослушивает сообщения)

. Главное здесь - порядок выполнения. Это

КОГДА что-то будет запущено

Когда вы совершаете вызов с использованием AJAX для внешней стороны или выполняете любой асинхронный код (например, setTimeout), Javascript зависит от ответ, прежде чем он сможет продолжить.

Большой вопрос, когда он получит ответ? Ответ в том, что мы не знаем, поэтому цикл событий ждет, когда это сообщение скажет: «Эй, забери меня». Если JS просто ждал этого сообщения синхронно, ваше приложение замерзнет, ​​и оно сосать. Таким образом, JS продолжает выполнение следующего элемента в очереди, ожидая, пока сообщение не будет добавлено обратно в очередь.

Вот почему с асинхронной функциональностью мы используем вещи, называемые обратными вызовами. Это похоже на обещание буквально. Как и в I , обещание что-то вернуть в какой-то момент jQuery использует специальные обратные вызовы, называемые deffered.done deffered.fail и deffered.always (среди других). Вы можете увидеть их все здесь

Итак, вам нужно передать функцию, которая в какой-то момент будет выполнена с переданными ей данными.

Поскольку обратный вызов не выполняется немедленно, но в более позднее время важно передать ссылку на функцию, которую она не выполнила. поэтому

function foo(bla) {
  console.log(bla)
}

, поэтому большую часть времени (но не всегда) вы пройдете foo не foo()

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

224
задан shA.t 21 May 2015 в 09:20
поделиться

20 ответов

Я бы определил функцию:

delimiter $$
DROP FUNCTION IF EXISTS `getFakeId`$$
CREATE FUNCTION `getFakeId`() RETURNS int(11)
    DETERMINISTIC
begin
return if(@fakeId, @fakeId:=@fakeId+1, @fakeId:=1);
end$$

, тогда я мог бы сделать:

select getFakeId() as id, t.* from table t, (select @fakeId:=0) as t2;

Теперь у вас нет подзапроса, который у вас не может быть в просмотров.

89
ответ дан Community 25 August 2018 в 18:06
поделиться

Я также проголосую за решение Мости Мостачо с незначительной модификацией его кода запроса:

SELECT a.i, a.j, (
    SELECT count(*) from test b where a.j >= b.j AND a.i = b.i
) AS row_number FROM test a

Что даст тот же результат:

+------+------+------------+
|    i |    j | row_number |
+------+------+------------+
|    1 |   11 |          1 |
|    1 |   12 |          2 |
|    1 |   13 |          3 |
|    2 |   21 |          1 |
|    2 |   22 |          2 |
|    2 |   23 |          3 |
|    3 |   31 |          1 |
|    3 |   32 |          2 |
|    3 |   33 |          3 |
|    4 |   14 |          1 |
+------+------+------------+

для таблицы:

+------+------+
|    i |    j |
+------+------+
|    1 |   11 |
|    1 |   12 |
|    1 |   13 |
|    2 |   21 |
|    2 |   22 |
|    2 |   23 |
|    3 |   31 |
|    3 |   32 |
|    3 |   33 |
|    4 |   14 |
+------+------+

С той лишь разницей, что запрос не использует JOIN и GROUP BY, вместо этого полагается на вложенный выбор.

13
ответ дан abcdn 25 August 2018 в 18:06
поделиться

Это позволяет использовать те же функции, что и ROW_NUMBER () AND PARTITION BY в MySQL

SELECT  @row_num := IF(@prev_value=GENDER,@row_num+1,1) AS RowNumber
       FirstName, 
       Age,
       Gender,
       @prev_value := GENDER
  FROM Person,
      (SELECT @row_num := 1) x,
      (SELECT @prev_value := '') y
  ORDER BY Gender, Age DESC
1
ответ дан Alankar 25 August 2018 в 18:06
поделиться

Немного поздно, но может помочь и тем, кто ищет ответы ...

Между строками / row_number example - рекурсивный запрос, который может использоваться в любом SQL:

WITH data(row_num, some_val) AS 
(
 SELECT 1 row_num, 1 some_val FROM any_table --dual in Oracle
  UNION ALL
 SELECT row_num+1, some_val+row_num FROM data WHERE row_num < 20 -- any number
)
SELECT * FROM data
 WHERE row_num BETWEEN 5 AND 10
/

ROW_NUM    SOME_VAL
-------------------
5           11
6           16
7           22
8           29
9           37
10          46
1
ответ дан Art 25 August 2018 в 18:06
поделиться
SELECT 
    @i:=@i+1 AS iterator, 
    t.*
FROM 
    tablename AS t,
    (SELECT @i:=0) AS foo
55
ответ дан ArtB 25 August 2018 в 18:06
поделиться

Ознакомьтесь с этой статьей, она показывает, как имитировать SQL ROW_NUMBER () с разделом в MySQL. Я столкнулся с тем же самым сценарием в реализации WordPress. Мне нужен ROW_NUMBER (), и его там не было.

http://www.explodybits.com/2011/11/mysql-row-number/

В примере в статье используется один разделять по полю. Чтобы разделить дополнительные поля, вы можете сделать что-то вроде этого:

  SELECT  @row_num := IF(@prev_value=concat_ws('',t.col1,t.col2),@row_num+1,1) AS RowNumber
         ,t.col1 
         ,t.col2
         ,t.Col3
         ,t.col4
         ,@prev_value := concat_ws('',t.col1,t.col2)
    FROM table1 t,
         (SELECT @row_num := 1) x,
         (SELECT @prev_value := '') y
   ORDER BY t.col1,t.col2,t.col3,t.col4 

Использование concat_ws обрабатывает null. Я проверил это на 3 поля, используя int, date и varchar. Надеюсь это поможет. Просмотрите статью, так как она нарушает этот запрос и объясняет это.

25
ответ дан birch 25 August 2018 в 18:06
поделиться

Это также может быть решением:

SET @row_number = 0;

SELECT 
    (@row_number:=@row_number + 1) AS num, firstName, lastName
FROM
    employees
1
ответ дан DaFois 25 August 2018 в 18:06
поделиться

Это отлично работает для меня, чтобы создать RowNumber, когда у нас есть несколько столбцов. В этом случае две колонки.

SELECT @row_num := IF(@prev_value= concat(`Fk_Business_Unit_Code`,`NetIQ_Job_Code`), @row_num+1, 1) AS RowNumber, 
    `Fk_Business_Unit_Code`,   
    `NetIQ_Job_Code`,  
    `Supervisor_Name`,  
    @prev_value := concat(`Fk_Business_Unit_Code`,`NetIQ_Job_Code`)  
FROM (SELECT DISTINCT `Fk_Business_Unit_Code`,`NetIQ_Job_Code`,`Supervisor_Name`         
      FROM Employee    
      ORDER BY `Fk_Business_Unit_Code`, `NetIQ_Job_Code`, `Supervisor_Name` DESC) z,  
(SELECT @row_num := 1) x,  
(SELECT @prev_value := '') y  
ORDER BY `Fk_Business_Unit_Code`, `NetIQ_Job_Code`,`Supervisor_Name` DESC
-1
ответ дан gawi 25 August 2018 в 18:06
поделиться

Из MySQL 8.0.0 и выше вы можете использовать оконные функции.

1.4 Что нового в MySQL 8.0 :

Функции окна ,

MySQL теперь поддерживает функции окна, которые для каждой строки из запроса выполняют вычисление с использованием строк, относящихся к этой строке. К ним относятся такие функции, как RANK (), LAG () и NTILE (). Кроме того, в качестве функций окна можно использовать несколько существующих совокупных функций; (g7) ROW_NUMBER () over_clause :

Возвращает номер текущего строка внутри своего раздела. Номера строк варьируются от 1 до количества строк раздела.

ORDER BY влияет на порядок, в котором строки нумеруются. Без ORDER BY нумерация строк является неопределенной.

Демо:

CREATE TABLE Table1(
  id INT AUTO_INCREMENT PRIMARY KEY, col1 INT,col2 INT, col3 TEXT);

INSERT INTO Table1(col1, col2, col3)
VALUES (1,1,'a'),(1,1,'b'),(1,1,'c'),
       (2,1,'x'),(2,1,'y'),(2,2,'z');

SELECT 
    col1, col2,col3,
    ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col3 DESC) AS intRow
FROM Table1;

DBFiddle Demo

11
ответ дан Lukasz Szozda 25 August 2018 в 18:06
поделиться

В MySQL нет функции, такой как rownum, row_num(), но путь примерно такой:

select 
      @s:=@s+1 serial_no, 
      tbl.* 
from my_table tbl, (select @s:=0) as s;
8
ответ дан Md. Kamruzzaman 25 August 2018 в 18:06
поделиться

Также немного поздно, но сегодня у меня была такая же потребность, поэтому я искал в Google и, наконец, простой общий подход, найденный здесь в статье Pinal Dave http://blog.sqlauthority.com/2014/03/09 / mysql-reset-row-number-for-each-group-partition-by-row-number /

Я хотел сосредоточиться на первоначальном вопросе Павла (это тоже моя проблема) поэтому я обобщаю свое решение как рабочий пример.

Beacuse мы хотим разделить на два столбца, я бы создал переменную SET во время итерации, чтобы определить, была ли запущена новая группа.

SELECT col1, col2, col3 FROM (
  SELECT col1, col2, col3,
         @n := CASE WHEN @v = MAKE_SET(3, col1, col2)
                    THEN @n + 1 -- if we are in the same group
                    ELSE 1 -- next group starts so we reset the counter
                END AS row_number,
         @v := MAKE_SET(3, col1, col2) -- we store the current value for next iteration
    FROM Table1, (SELECT @n := 0, @v := NULL) r -- helper table for iteration with startup values
   ORDER BY col1, col2, col3 DESC -- because we want the row with maximum value
) x WHERE row_number = 1 -- and here we select exactly the wanted row from each group

Средство 3 при первом параметре MAKE_SET, которое я хочу, имеет значение в SET (3 = 1 | 2). Конечно, если у нас нет двух или более столбцов, строящих группы, мы можем исключить операцию MAKE_SET. Конструкция точно такая же. Это работает для меня, как требуется. Большое спасибо Пиналу Дейву за его четкую демонстрацию.

1
ответ дан Miklos Krivan 25 August 2018 в 18:06
поделиться

Я всегда заканчиваю этот шаблон. Учитывая эту таблицу:

+------+------+
|    i |    j |
+------+------+
|    1 |   11 |
|    1 |   12 |
|    1 |   13 |
|    2 |   21 |
|    2 |   22 |
|    2 |   23 |
|    3 |   31 |
|    3 |   32 |
|    3 |   33 |
|    4 |   14 |
+------+------+

Вы можете получить этот результат:

+------+------+------------+
|    i |    j | row_number |
+------+------+------------+
|    1 |   11 |          1 |
|    1 |   12 |          2 |
|    1 |   13 |          3 |
|    2 |   21 |          1 |
|    2 |   22 |          2 |
|    2 |   23 |          3 |
|    3 |   31 |          1 |
|    3 |   32 |          2 |
|    3 |   33 |          3 |
|    4 |   14 |          1 |
+------+------+------------+

Запустив этот запрос, который не нуждается в какой-либо переменной:

SELECT a.i, a.j, count(*) as row_number FROM test a
JOIN test b ON a.i = b.i AND a.j >= b.j
GROUP BY a.i, a.j

Надеюсь, что это поможет!

72
ответ дан Mosty Mostacho 25 August 2018 в 18:06
поделиться

В MySQL нет рейтинговой функциональности. Самое близкое, что вы можете получить, это использовать переменную:

SELECT t.*, 
       @rownum := @rownum + 1 AS rank
  FROM YOUR_TABLE t, 
       (SELECT @rownum := 0) r

, и как это будет работать в моем случае? Мне нужны две переменные: по одному для каждого из col1 и col2? Col2 нужно будет как-то сбросить, когда col1 изменится.?

Да. Если бы это был Oracle, вы могли бы использовать функцию LEAD для достижения пика при следующем значении. К счастью, Quassnoi охватывает логику того, что вам нужно реализовать в MySQL .

184
ответ дан OMG Ponies 25 August 2018 в 18:06
поделиться

MariaDB 10.2 реализует «Функции окна», включая RANK (), ROW_NUMBER () и несколько других вещей:

https://mariadb.com/kb/en/mariadb/window -функции /

Основываясь на разговоре в Percona Live в этом месяце, они достаточно хорошо оптимизированы.

Синтаксис идентичен коду в Вопросе.

3
ответ дан Rick James 25 August 2018 в 18:06
поделиться

Я не вижу никакого простого ответа, охватывающего часть «PARTITION BY», поэтому вот мой:

SELECT
    *
FROM (
    select
        CASE WHEN @partitionBy_1 = l THEN @row_number:=@row_number+1 ELSE @row_number:=1 END AS i
        , @partitionBy_1:=l AS p
        , t.*
    from (
        select @row_number:=0,@partitionBy_1:=null
    ) as x
    cross join (
        select 1 as n, 'a' as l
        union all
        select 1 as n, 'b' as l    
        union all
        select 2 as n, 'b' as l    
        union all
        select 2 as n, 'a' as l
        union all
        select 3 as n, 'a' as l    
        union all    
        select 3 as n, 'b' as l    
    ) as t
    ORDER BY l, n
) AS X
where i > 1
  • Предложение ORDER BY должно отражать вашу потребность в ROW_NUMBER. Таким образом, уже существует явное ограничение: вы не можете одновременно иметь несколько эмуляторов ROW_NUMBER этой формы.
  • Порядок «вычисленного столбца» имеет значение . Если у вас mysql вычислить эти столбцы в другом порядке, это может не сработать.
  • В этом простом примере я помещаю только один, но вы можете иметь несколько частей «PARTITION BY»
        CASE WHEN @partitionBy_1 = part1 AND @partitionBy_2 = part2 [...] THEN @row_number:=@row_number+1 ELSE @row_number:=1 END AS i
        , @partitionBy_1:=part1 AS P1
        , @partitionBy_2:=part2 AS P2
        [...] 
    FROM (
        SELECT @row_number:=0,@partitionBy_1:=null,@partitionBy_2:=null[...]
    ) as x
    
1
ответ дан Serge Profafilecebook 25 August 2018 в 18:06
поделиться

запрос для row_number в mysql

set @row_number=0;
select (@row_number := @row_number +1) as num,id,name from sbs
6
ответ дан Sjon 25 August 2018 в 18:06
поделиться

Решение, которое я нашел лучшим, это использовать подзапрос, подобный этому:

SELECT 
    col1, col2, 
    (
        SELECT COUNT(*) 
        FROM Table1
        WHERE col1 = t1.col1
        AND col2 = t1.col2
        AND col3 > t1.col3
    ) AS intRow
FROM Table1 t1

Столбцы PARTITION BY просто сравниваются с '=' и разделяются символом AND. Столбцы ORDER BY будут сравниваться с '& lt;' или '>', и разделены OR.

Я нашел, что это очень гибко, даже если это немного дорого.

4
ответ дан snydergd 25 August 2018 в 18:06
поделиться
set @i = 1;  
INSERT INTO ARG_VALUE_LOOKUP(ARG_VALUE_LOOKUP_ID,ARGUMENT_NAME,VALUE,DESCRIPTION,UPDATE_TIMESTAMP,UPDATE_USER,VER_NBR,OBJ_ID) 
select @i:= @i+1 as ARG_VALUE_LOOKUP_ID,ARGUMENT_NAME,VALUE,DESCRIPTION,CURRENT_TIMESTAMP,'admin',1,UUID() 
FROM TEMP_ARG_VALUE_LOOKUP 
order by ARGUMENT_NAME;
-1
ответ дан Taryn 25 August 2018 в 18:06
поделиться
SELECT 
    col1, col2, 
    count(*) as intRow
FROM Table1
GROUP BY col1,col2
ORDER BY col3 desc
-5
ответ дан user2807083 25 August 2018 в 18:06
поделиться

Невозможно воспроизвести функциональность брутабеля. Вы можете получить ожидаемые результаты, но скорее всего вы будете разочарованы на определенном этапе. Вот что говорит документация mysql:

Для других операторов, таких как SELECT, вы можете получить ожидаемые результаты, но это не гарантируется. В следующем утверждении вы можете подумать, что MySQL сначала оценит @a, а затем выполнит второе задание: SELECT @a, @a: = @ a + 1, ...; Однако порядок оценки выражений с использованием пользовательских переменных не определен.

С уважением, Георги.

4
ответ дан user3503199 25 August 2018 в 18:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: