MySQL - возможно ли объединить запросы на выборку, чтобы не выполнять в цикле while? - PullRequest
0 голосов
/ 06 ноября 2019

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

Теперь внутри цикла while я должен был использовать запрос select count, чтобы подсчитать, сколько невидимых элементов есть у каждого пользователя, и это занимает слишком много времени, если в цикле так много результатов.

Есть ли способ выполнить запрос без выполнения запроса select внутри цикла while?

Например:

SELECT  categories.name, 
        quality.name, 
        users.regdate,
        categories.name,
        items.name, 
        items.visible,
        items.owner,
        users.username
        FROM items
        LEFT JOIN users ON items.owner = users.id 
        LEFT JOIN categories ON items.category = categories.id 
        LEFT JOIN quality on items.category_quality = quality.id
        WHERE items.visible = 'no'

Теперь в цикле while для получения количества элементов, япришлось запросить

while($row = mysqli_fetch_assoc($sql))
{
$all_items_by_user = "SELECT COUNT(items.name)
FROM items
WHERE items.owner = ".$row['owner']."";

$visible_items_by_user = "SELECT COUNT(items.name)
FROM items
WHERE items.owner = ".$row['owner']." AND items.visible = 'yes'";

// rest of code here.
// when there are 200 items in loop executing time goes crazy 
// (6+ secs, where with 1 item it's around 0.05)
}

Редактировать с примером:

Некоторые люди спрашивали, какой будет окончательный код, я постараюсь дать лучшее, что могу.

Игнорировать левые соединения, так как это не относится к делу, я просто добавил их из всего запроса.

Id | item name | owner | Visible
1 | Item 1 | 2 | no
2 | Item 2 | 2 | yes
3 | Item 3 | 2 | no
4 | Item 4 | 2 | no
5 | Item 5 | 2 | no
6 | Item 6 | 3 | no
7 | Item 7 | 3 | no
8 | Item 8 | 3 | no
9 | Item 9 | 4 | no
10 | Item 10 | 4 | no

В цикле while для каждого пользователя он должен подсчитать, сколько строк принадлежит пользователю.

Например: пользователю 2 принадлежит всего 5 строк и 4 скрыты, ($ all_items_by_user будет считать все, а $ visible_items_by_user будет считать только 1) пользователю 3 принадлежит 3 строки, пользователю 4 принадлежит 2 строки.

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

Окончательный результат должен быть

while($row = mysqli_fetch_assoc($sql))
{
$all_items_by_user = "SELECT COUNT(items.name)
FROM items
WHERE items.owner = ".$row['owner']."";

$visible_items_by_user = "SELECT COUNT(items.name)
FROM items
WHERE items.owner = ".$row['owner']." AND items.visible = 'yes'";

echo $row['owner'] . "(Visible items: number | All items: number";
// Output: 2 (Visible items: 1 | All items: 5)
}

Ответы [ 2 ]

0 голосов
/ 06 ноября 2019

Это предполагает, что вы только заботитесь о подсчете на пользователя, и что вы не заботитесь о какой-либо конкретной информации

SELECT items.owner,
    COUNT(items.name) AS itemCount, 
    SUM( CASE WHEN items.visible = 'yes' AND item.name IS NOT NULL
            THEN 1 ELSE 0 END) AS visibleCount
    FROM items 
    GROUP BY items.owner

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

DEMO

0 голосов
/ 06 ноября 2019

Вы можете избежать запросов в цикле, используя объединение для подзапроса агрегированных результатов

SELECT  categories.name, 
        quality.name, 
        users.regdate,
        categories.name,
        items.name, 
        items.visible,
        items.owner,
        users.username,
        ifnull(t.count_name,0), 
        ifnull(t.count_visible_name,0)
        FROM items
        LEFT JOIN users ON items.owner = users.id 
        LEFT JOIN categories ON items.category = categories.id 
        LEFT JOIN quality on items.category_quality = quality.id 
        LEFT JOIN  (
          select items.owner
            , COUNT(items.name) count_name
            , sum( case when items.visible = 'yes' AND item.name is not null
                then 1 else 0 end) count_visible_name
          from items 
          group by items.owner

        ) t on t.owner = items.owner 

убедитесь, что у вас есть правильный составной индекс

 on table  items column(owner, category, category_quality)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...