SQL-запрос с несколькими значениями в одном столбце. Несколько sql запросов в одном


Несколько SELECT COUNT в одном запросе MySQL

В данной небольшой статье речь пойдет о базах данных в частности MySQL, выборке и подсчете. Работая с базами данных, часто требуется совершить подсчет количества строк COUNT() с определенным условием или без, это сделать крайне просто следующим запросом

Запрос вернет значение, с количеством строк в таблице.

Подсчет с условием

Запрос вернет значение, с количеством строк в таблице удовлетворяющих данному условию: var = 1

Для получения нескольких значений подсчета строк с разными условиями, можно поочередно выполнить несколько запросов, например

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

Таким образом выполнив всего один запрос к базе данных, мы получаем результат с подсчетом количества строк по нескольким условиям, содержащий несколько значений подсчета, например

c1|c2|c3 -------- 1 |5 |8

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

Следующий пример запроса, содержащего несколько COUNT в одном запросе MySQL, построен несколько иначе, в нем используются конструкции IF(условие, значение1, значение2), а также суммирование SUM(). Позволяющие произвести отбор данных по заданным критериям в рамках одного запроса, затем суммировать их, и вывести несколько значений в качестве результата.

Как видно из запроса, он построен достаточно лаконично, но скорость его выполнения тоже не порадовала, результат данного запроса будет следующий,

total|c1|c2|c3 -------------- 14 |1 |5 |8

Далее я приведу сравнительную статистику скорости выполнения трех вариантов запросов, для выборки нескольких COUNT(). Для тестирования скорости выполнения запросов, было выполнено по 1000 запросов каждого типа, с таблицей содержащей более трех тысяч записей. При этом каждый раз запрос содержал SQL_NO_CACHE для отключение кеширования результатов базой данных.

Скорость выполненияТри отдельных запроса: 0.9 секОдин запрос с подзапросами: 0.95 секОдин запрос с конструкцией IF и SUM: 1.5 сек

Вывод. И так, мы имеет несколько вариантов построения запросов к базе данных MySQL с несколькими COUNT(), первый вариант с отдельными запросами не очень удобен, но имеет наилучший результат по скорости. Второй вариант с подзапросами несколько удобнее, но при этом скорость его выполнение немного ниже. И наконец третий лаконичный вариант запроса с конструкциями IF и SUM, кажущийся самым удобным, имеет самую низкую скорость выполнения, которая почти в два раза ниже первых двух вариантов. По этому, при задаче оптимизации работы БД, я рекомендую использовать второй вариант запроса содержащий подзапросы с COUNT(), во первых его скорость выполнения близка к самому быстрому результату, во вторых такая организация внутри одного запроса достаточно удобна.

Похожие записи

rche.ru

Несколько счетчиков в одном запросе SQL Безопасный SQL

Я пытаюсь получить количество документов в 4 конкретных разделах, используя следующий код:

SELECT category.id , category.title , count(ts1.section_id) AS doc1 , count(ts2.section_id) AS doc2 , count(ts3.section_id) AS doc3 , count(ts4.section_id) AS doc4 FROM category LEFT JOIN category_link_section AS ts1 ON (category.id = ts1.category_id AND ts1.section_id = 1) LEFT JOIN category_link_section AS ts2 ON (category.id = ts2.category_id AND ts2.section_id = 2) LEFT JOIN category_link_section AS ts3 ON (category.id = ts3.category_id AND ts3.section_id = 3) LEFT JOIN category_link_section AS ts4 ON (category.id = ts4.category_id AND ts4.section_id = 4) GROUP BY category.id, ts1.section_id, ts2.section_id, ts3.section_id, ts4.section_id

Таблица «category» имела идентификатор, заголовок и т. Д. В таблице «category_link_section» содержатся ссылки id между категориями, категориями_ид и doc_id.

Если счетчик равен 0 для любого столбца, он отображает 0 в этом столбце. Но если результат не равен 0, он показывает результат умножения всех результатов секции. Поэтому, если бы мои 4 столбца подсчета должны были возвращаться: 1, 2, 0, 3; на самом деле это будет 6, 6, 0, 6;

Если я использую этот следующий код для каждой конкретной категории, я получаю результаты, которые я хочу:

SELECT category.id , category.title , count(ts1.section_id) AS doc1 FROM category LEFT JOIN category_link_section AS ts1 ON (category.id = ts1.category_id AND ts1.section_id = 1) GROUP BY category.id, ts1.section_id

но мне тогда нужно циклически перебирать базу данных каждый раз для каждого раздела.

Поэтому мой вопрос: нужно ли мне перешагнуть и вызвать каждый раздел по очереди, построив таблицу вне SQL, или это можно сделать в одном запросе?

Solutions Collecting From Web of "Несколько счетчиков в одном запросе SQL"

@ Ответ VoteyDisciple находится на правильном пути, но его запрос нуждается в некоторых улучшениях:

SELECT c.id, c.title, SUM(ts1.section_id = 1) AS doc1, SUM(ts1.section_id = 2) AS doc2, SUM(ts1.section_id = 3) AS doc3, SUM(ts1.section_id = 4) AS doc4 FROM category AS c LEFT JOIN category_link_section AS ts1 ON (c.id = ts1.category_id) GROUP BY c.id;

Пояснения:

  • Выражения IF() являются избыточными, поскольку равенство уже возвращает 1 или 0.
  • Возьмите ts1.section_id=1 из условия соединения или вы никогда не получите другие значения section_id .
  • Группа только по c.id Я предполагаю, что OP только хочет одну строку для каждой категории и столбцы для подсчета каждого значения section_id для соответствующей категории. Если запрос сгруппирован по c.id, ts1.section_id , тогда будет до четырех строк для каждой категории.
  • Перемещайте запятые в списке выбора. Запястья, плавающие в начале строки, выглядят уродливыми. 😉

Возможно, вы захотите попробовать что-то вроде этого:

SELECT category.id , category.title , SUM(IF(ts1.section_id = 1, 1, 0)) AS doc1 , SUM(IF(ts1.section_id = 2, 1, 0)) AS doc2 , SUM(IF(ts1.section_id = 3, 1, 0)) AS doc3 , SUM(IF(ts1.section_id = 4, 1, 0)) AS doc4 FROM category LEFT JOIN category_link_section AS ts1 ON (category.id = ts1.category_id AND ts1.section_id = 1) GROUP BY category.id, ts1.section_id

sql.fliplinux.com

подсчитывать несколько столбцов в одном запросе Безопасный SQL

Ребята, у меня есть четыре вопроса:

Запрос №1:

select satisfaction_score,count(satisfaction_score) as Satisfaction_count from j_survey_response where satisfaction_score != 0 group by satisfaction_score

Выход будет

Удовлетворение удовлетворенности 1 5 2 8 3 97 4 329 5 859

Запрос № 2:

select response_score,count(response_score) as response_count from j_survey_response where response_score != 0 group by response_score

ВЫВОД

response_score response_count 1 28 2 8 3 42 4 250 5 980

Запрос № 3:

select responder_score,count(responder_score) as responder_count from j_survey_response where responder_score != 0 group by responder_score

ВЫВОД

responder_score responder_count 1 24 2 3 3 30 4 236 5 987

Запрос № 4:

select service_score,count(service_score) as service_count from j_survey_response where service_score != 0 group by service_score

ВЫВОД

service_score service_count 1 22 2 2 3 34 4 270 5 966

Но мне нужен вывод, как показано ниже.

оценка satisf_count response_count responder_count service_count 1 5 28 24 22 2 8 8 3 2 3 97 42 30 34 4 329 250 236 270 5 859 980 986 966
Solutions Collecting From Web of "подсчитывать несколько столбцов в одном запросе"

Вы можете использовать UNION ALL отдельные запросы и применять условную агрегацию в результирующем наборе:

select score, max(case when type = 'satisfaction' then count end) as satisfaction_count, max(case when type = 'response' then count end) as response_count, max(case when type = 'responder' then count end) as responder_count, max(case when type = 'service' then count end) as service_count from ( select satisfaction_score as score, count(satisfaction_score) as count, 'satisfaction' as type from j_survey_response where satisfaction_score != 0 group by satisfaction_score union all select response_score, count(response_score) as count, 'response' as type from j_survey_response where response_score != 0 group by response_score union all select responder_score, count(responder_score) as count, 'responder' as type from j_survey_response where responder_score != 0 group by responder_score union all select service_score, count(service_score) as count, 'service' as type from j_survey_response where service_score != 0 group by service_score) as t group by score

Переместите их в подзапросы и соедините их с помощью колонок. Как это

select q1.satisfaction_score as score, q1.satisfaction_count, q2.response_count, q3.responder_count , q4.service_count, from (query 1) q1 join (query 2) q2 on q1.satisfaction_score=q2.response_score join (query 3) q3 on q1.satisfaction_score=q3.responder_score join (query 4) q4 on q1.satisfaction_score=q3.service_score

Вы пытаетесь выполнить этот запрос Sql

select service_score , count(satisfaction_score) as Satisfaction_count, count(response_score) as response_count,count(responder_score) as `responder_count, count(service_score) as service_count from j_survey_response where service_score != 0 and responder_score != 0 and response_score != 0 and satisfaction_score != 0`

если вы используете группу по

select service_score , count(satisfaction_score) as Satisfaction_count, count(response_score) as response_count,count(responder_score) as `responder_count, count(service_score) as service_count from j_survey_response where service_score != 0 and responder_score != 0 and response_score != 0 and satisfaction_score != 0` group by satisfaction_score,response_score,responder_score,service_score

sql.fliplinux.com

sql - SQL-запрос с несколькими значениями в одном столбце

Вам действительно не следует хранить несколько элементов в одном столбце, если ваш SQL когда-либо захочет обрабатывать их по отдельности. "Гимнастика SQL", которую вы должны выполнять в этих случаях, - это как уродливые хаки, так и ухудшение производительности.

Идеальное решение состоит в том, чтобы разделить отдельные элементы на отдельные столбцы и для 3NF переместить эти столбцы в отдельную таблицу в виде строк, если вы действительно хотите сделать это правильно (но детские шаги, вероятно, все в порядке, если вы уверены, что там никогда не будет более двух причин в краткосрочной и среднесрочной перспективе).

Затем ваши запросы будут проще и быстрее.

Однако, если это не вариант, вы можете использовать вышеупомянутую гимнастику SQL, чтобы сделать что-то вроде:

where find ( ',' |fld| ',', ',02,' ) > 0

Предполагая, что ваш SQL-диалект имеет функцию поиска строк (find в этом случае, но я думаю charindex для SQLServer).

Это гарантирует, что все подколоны начинаются и начинаются с запятой (запятая плюс поле плюс запятая) и искать конкретное требуемое значение (с запятыми с обеих сторон, чтобы обеспечить полное соответствие столбца).

Если вы не можете контролировать то, что приложение помещает в этот столбец, я бы выбрал решение DBA. Решения DBA определяются как те, которые DBA должен делать, чтобы обойти недостатки своих пользователей: -).

Создайте два новых столбца в этой таблице и создайте триггер insert/update, который заполнит их двумя причинами, которые пользователь помещает в исходный столбец.

Затем запросите эти два новых столбца для определенных значений, а не попытайтесь разделить старый столбец.

Это означает, что затраты на разделение только на вставку/обновление строки, а не на все единичные select`, амортизирующие, что экономически выгодно.

Тем не менее, мой ответ - повторить схему. Это будет лучшим способом в долгосрочной перспективе с точки зрения скорости, читаемых запросов и ремонтопригодности.

qaru.site

SQL-запрос с несколькими значениями в одном столбце Безопасный SQL

Я бил головой по столу, пытаясь понять это. У меня есть таблица, в которой хранятся данные о работе, и причины, по которым работа не завершается. Причины – числовые, 01,02,03 и т. Д. У вас могут быть две причины для ожидающей работы. Если вы выберете две причины, они будут сохранены в том же столбце, разделенном запятой. Это пример из таблицы JOBID :

Существует другая таблица с именем Pending , которая хранит то, что фактически представляют эти значения. 01 = Недостаточно информации, 02 = Недостаточно времени, 03 = Просмотр ожидания. Пример:

То, что я пытаюсь сделать, – это запросить базу данных, чтобы дать мне все номера заданий, пользователей, pendinginfo и ожидающую причину. Я могу вырвать первое значение, но не могу понять, как сделать второе. Каковы мои ограниченные навыки:

То, что я хотел бы увидеть для этого примера, было бы следующим:

Вы действительно не должны хранить несколько элементов в одном столбце, если ваш SQL когда-либо захочет обрабатывать их по отдельности. «Гимнастика SQL», которую вы должны выполнять в этих случаях, – это как уродливые хаки, так и ухудшение производительности.

Идеальное решение состоит в том, чтобы разделить отдельные элементы на отдельные столбцы и для 3NF переместить эти столбцы в отдельную таблицу в виде строк, если вы действительно хотите сделать это правильно (но детские шаги, вероятно, все в порядке, если вы уверены, что никогда не будет более двух причин в краткосрочной и среднесрочной перспективе).

Тогда ваши запросы будут проще и быстрее.

Однако, если это не вариант, вы можете использовать вышеупомянутую гимнастику SQL, чтобы сделать что-то вроде:

where find ( ',' |fld| ',', ',02,' ) > 0

предполагая, что ваш SQL-диалект имеет функцию поиска строк ( find в этом случае, но я думаю, что charindex для SQLServer).

Это обеспечит запуск всех подпоследовательностей и начнется с запятой (запятая плюс поле плюс запятая) и найдите конкретное требуемое значение (с запятыми с обеих сторон, чтобы убедиться, что это полное совпадение столбцов).

Если вы не можете контролировать то, что приложение помещает в этот столбец, я бы выбрал решение DBA – решения DBA определяются как те, которые DBA должен делать, чтобы обойти недостатки своих пользователей :-).

Создайте два новых столбца в этой таблице и создайте триггер insert / update, который заполнит их двумя причинами, которые пользователь помещает в исходный столбец.

Затем запросите эти два новых столбца для определенных значений, а не попытайтесь разделить старый столбец.

Это означает, что стоимость расщепления заключается только в вставке / обновлении строки, а не на любом отдельном select`, амортизируя, что экономически эффективно.

Тем не менее, мой ответ – повторить схему. Это будет лучшим способом в долгосрочной перспективе с точки зрения скорости, читаемых запросов и ремонтопригодности.

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

JOBS TABLE jobID | userID -------------- 1 | user13 2 | user32 3 | user44 -------------- PENDING TABLE pendingID | pendingText --------------------------- 01 | Not Enough Info 02 | Not Enough Time --------------------------- JOB_PENDING TABLE jobID | pendingID ----------------- 1 | 01 1 | 02 2 | 01 3 | 03 3 | 01 -----------------

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

У меня есть таблицы вроде:

Events --------- eventId int eventTypeIds nvarchar(50) ... EventTypes -------------- eventTypeId Description ...

Каждое событие может содержать несколько типов событий.

Все, что я делаю, это написать 2 процедуры в моем коде сайта, а не код SQL

  1. Одна процедура преобразует значение поля таблицы (eventTypeIds) как «3,4,15,6» в массив ViewState, поэтому я могу использовать его где угодно в коде.

  2. Эта процедура делает наоборот, она собирает любые параметры, которые вы проверили, и преобразует их в

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

Взгляните на аналогичный вопрос, который я ответил здесь

;WITH Numbers AS ( SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 0)) AS N FROM JobId ), Split AS ( SELECT JOB_NUMBER, USER_ASSIGNED, SUBSTRING(PENDING_INFO, Numbers.N, CHARINDEX(',', PENDING_INFO + ',', Numbers.N) - Numbers.N) AS PENDING_NUM FROM JobId JOIN Numbers ON Numbers.N <= DATALENGTH(PENDING_INFO) + 1 AND SUBSTRING(',' + PENDING_INFO, Numbers.N, 1) = ',' ) SELECT * FROM Split JOIN Pending ON Split.PENDING_NUM = Pending.PENDING_NUM

Основная идея заключается в том, что вы должны умножать каждую строку столько раз, сколько PENDING_NUM . Затем извлеките соответствующую часть строки

Хотя я согласен с перспективой DBA не хранить несколько значений в одном поле, это выполнимо, как показано ниже, практично для логики приложения и некоторых проблем с производительностью.

Скажем, у вас 10000 групп пользователей, каждая из которых имеет в среднем 1000 членов. Вы можете иметь таблицу user_groups с такими столбцами, как groupID и membersID. Столбец membersID можно заполнить следующим образом: (', 10,2001,20003,333,4520,'), каждый из которых является идентификатором-членом, все разделяются запятой. Добавьте также запятую в начале и конце данных. Тогда ваш выбор будет использоваться как «%, someID,%».

Если вы не можете изменить свои данные ('01, 02,03 ') или аналогичные, скажем, вам нужны строки, содержащие 01, вы все равно можете использовать «select … LIKE '01,%' OR '%, 01' OR '% , 01,% '", который гарантирует, что он будет соответствовать, если в начале, в конце или внутри, избегая аналогичного числа (то есть: 101).

sql.fliplinux.com

MySQL Несколько соединений в одном запросе? Безопасный SQL

Вы можете просто добавить другое соединение следующим образом:

SELECT dashboard_data.headline, dashboard_data.message, dashboard_messages.image_id, images.filename FROM dashboard_data INNER JOIN dashboard_messages ON dashboard_message_id = dashboard_messages.id INNER JOIN images ON dashboard_messages.image_id = images.image_id

Однако имейте в виду, что, поскольку это INNER JOIN , если у вас есть сообщение без изображения, вся строка будет пропущена. Если это возможно, вы можете сделать LEFT OUTER JOIN который вернет все ваши сообщения панели мониторинга и имя_файла только в том случае, если он существует (иначе вы получите нуль)

SELECT dashboard_data.headline, dashboard_data.message, dashboard_messages.image_id, images.filename FROM dashboard_data INNER JOIN dashboard_messages ON dashboard_message_id = dashboard_messages.id LEFT OUTER JOIN images ON dashboard_messages.image_id = images.image_id

Просто добавьте еще одно соединение:

SELECT dashboard_data.headline, dashboard_data.message, dashboard_messages.image_id, images.filename FROM dashboard_data INNER JOIN dashboard_messages ON dashboard_message_id = dashboard_messages.id INNER JOIN images ON dashboard_messages.image_id = images.image_id

Я поделился своим опытом использования двух LEFT JOINS в одном SQL-запросе.

У меня 3 таблицы:

Таблица 1) Пациент состоит из столбцов PatientID, PatientName

Таблица 2) Назначение состоит из столбцов AppointmentID, AppointmentDateTime, PatientID, DoctorID

Таблица 3) Доктор состоит из столбцов DoctorID, DoctorName

Запрос:

SELECT Patient.patientname, AppointmentDateTime, Doctor.doctorname FROM Appointment LEFT JOIN Doctor ON Appointment.doctorid = Doctor.doctorId //have doctorId column common LEFT JOIN Patient ON Appointment.PatientId = Patient.PatientId //have patientid column common WHERE Doctor.Doctorname LIKE 'varun%' // setting doctor name by using LIKE AND Appointment.AppointmentDateTime BETWEEN '1/16/2001' AND '9/9/2014' //comparison b/w dates ORDER BY AppointmentDateTime ASC; // getting data as ascending order

Я написал решение для получения формата даты, например «mm / dd / yy» (под моим именем «VARUN TEJ REDDY»)

sql.fliplinux.com

sql - Несколько запросов sql в одном результате

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

Мои 3 отдельных запроса:

SELECT ISNULL(SUM(ps.UnitsSold), 0) AS UnitsSold, ISNULL(pg.[Description], 'Other') AS [Description] FROM dbo.ProductSales ps LEFT OUTER JOIN dbo.Product p ON ps.ProductID = p.ProductID LEFT OUTER JOIN dbo.ProductGroupings pg ON p.[Asin] = pg.[Asin] WHERE (ps.OrderDate BETWEEN GETDATE() - 10 AND GETDATE() - 3) AND ps.DistributionCentreID IN (3) GROUP BY pg.[Description], ps.DistributionCentreID SELECT ISNULL(SUM(ps.UnitsSold), 0) AS UnitsSold, ISNULL(pg.[Description], 'Other') AS [Description] FROM dbo.ProductSales ps LEFT OUTER JOIN dbo.Product p ON ps.ProductID = p.ProductID LEFT OUTER JOIN dbo.ProductGroupings pg ON p.[Asin] = pg.[Asin] WHERE (ps.OrderDate BETWEEN GETDATE() - 17 AND GETDATE() - 10) AND ps.DistributionCentreID IN (3) GROUP BY pg.[Description], ps.DistributionCentreID SELECT ISNULL(SUM(ps.UnitsSold), 0) AS UnitsSold, ISNULL(pg.[Description], 'Other') AS [Description] FROM dbo.ProductSales ps LEFT OUTER JOIN dbo.Product p ON ps.ProductID = p.ProductID LEFT OUTER JOIN dbo.ProductGroupings pg ON p.[Asin] = pg.[Asin] WHERE (ps.OrderDate BETWEEN GETDATE() - 374 AND GETDATE() - 367) AND ps.DistributionCentreID IN (3) GROUP BY pg.[Description], ps.DistributionCentreID

Это приводит к таким же результатам (первый запрос):

UnitsSold Description 4154 desc1 764 desc2

и т.д..

О чем подумать, описание (группа продуктов) может не существовать в одном из запросов, поэтому мне нужно это учитывать.

В идеале мне хотелось бы выглядеть примерно так:

Description UnitsSoldThisWeek UnitsSoldLastWeek UnitsSoldLastYear Desc1 54 45 37

и т.д..

Любые вопросы, проблемы или сукинги из-за плохого запроса приемлемы, я рад улучшить свое понимание SQL.

Благодаря,

Майкл

источник поделиться

qaru.site