Как правильно использовать MySQL для получения данных из 4 строк, 1 столбца и разделения на 9 столбцов? - PullRequest
0 голосов
/ 14 октября 2019

Я изучил и перепробовал несколько дней запросов SQL, чтобы найти «что-то», которое будет работать. У меня есть таблица apj32_facileforms_subrecords, которая использует 7 столбцов. Все данные, которые я хочу отобразить, находятся в 1 столбце - «значение». «Запись» отображает номер записи. «Заголовок» - это то, что я хотел бы видеть в строке заголовка, но это не так важно, как «значение» для отображения в 1 строке на основе номера «записи». Я пробовал много CONCAT и различных запросов Pivot, но, кажется, ничто не может сделать больше, чем «приблизиться» к тому, что я хотел бы получить в качестве конечного результата. Вот снимок экрана с таблицей: enter image description here

Вывод «должен» быть линейным, так что 1 строка содержит 9 столбцов: Project;Индекс;Имя;Фамилия;Адрес;Город;Телефон;Электронное письмо;Торговля (в таком порядке). И значения в 9 столбцах взяты из «значения», так как они относятся к номеру «записи».

Я знаю, что есть много примеров, которые похожи, но я ничего не нашел обложек, принимающих все значенияот «value» и CONCAT до 1 строки.

Это работает для получения всех данных, которые я хочу - SELECT record, value ОТ apj32_facileforms_subrecords ГДЕ (record IN (record, *)1015 *)) ORDER BY record Но значения все еще находятся в нескольких строках. Я могу поиграть с этим запросом, чтобы получить только значения, но я все еще в растерянности, чтобы получить их в 1 строку. Я продолжу играть с этим запросом, чтобы выяснить, смогу ли я выяснить его, прежде чем один из экспертов здесь покажет мне, как это просто сделать. Любая помощь будет оценена.

1 Ответ

0 голосов
/ 15 октября 2019

Использование SQL для преобразования представления модели EAV в реляционное представление может быть несколько запутанным и не очень эффективным.

Два наиболее часто используемых подхода - это условное агрегирование и коррелированные подзапросы в списке SELECT. Оба подхода требуют тщательного индексирования для подходящей производительности с большими наборами.


коррелированные подзапросы пример

Вот пример подхода коррелированных подзапросов, чтобы получить одинзначение атрибута "zipcode" для некоторых записей

 SELECT r.id 
      , ( SELECT v1.value
            FROM `apj32_facileforms_subrecords` v1
           WHERE v1.record = r.id 
             AND v1.name   = 'zipcode'
           ORDER BY v1.value LIMIT 0,1
        ) AS `Zipcode`
   FROM ( SELECT 1 AS id ) r

Расширяя это, мы повторяем коррелированный подзапрос, изменяя идентификатор атрибута ('firstname' вместо 'zipcode'. похоже, мы могли бы также ссылатьсяэто по элементам, например, v2.element = 2

 SELECT r.id
      , ( SELECT v1.value
            FROM `apj32_facileforms_subrecords` v1
           WHERE v1.record = r.id 
             AND v1.name   = 'zipcode'
           ORDER BY v1.value LIMIT 0,1
        ) AS `Zipcode`

      , ( SELECT v2.value
            FROM `apj32_facileforms_subrecords` v2
           WHERE v2.record = r.id 
             AND v2.name   = 'firstname'
           ORDER BY v2.value LIMIT 0,1
        ) AS `First Name`  

      , ( SELECT v3.value
            FROM `apj32_facileforms_subrecords` v3
           WHERE v3.record = r.id 
             AND v3.name   = 'lastname'
           ORDER BY v3.value LIMIT 0,1
        ) AS `Last Name`

   FROM ( SELECT 1 AS id UNION ALL SELECT 2 ) r

возвращает что-то вроде

id  Zipcode  First Name  Last Name
--  -------  ----------  ---------
 1  98228    David       Bacon
 2  98228    David       Bacon 

условное агрегирование пример приближения

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

 SELECT r.id
      , MIN(IF(v.name  = 'zipcode'   ,v.value,NULL)) AS `Zip Code`
      , MIN(IF(v.name  = 'firstname' ,v.value,NULL)) AS `First Name`
      , MIN(IF(v.name  = 'lastname'  ,v.value,NULL)) AS `Last Name`
   FROM ( SELECT 1 AS id UNION ALL SELECT 2 ) r
   LEFT
   JOIN `apj32_facileforms_subrecords` v
     ON v.record = r.id
  GROUP
     BY r.id

Для более переносимого синтаксиса мы можем заменить MySQL *Функция 1029 * с более выражением стандарта ANSI CASE, например,

      , MIN(CASE v.name WHEN 'zipcode'   THEN v.value END) AS `Zip Code`

Обратите внимание, что MySQL не поддерживает синтаксис SQL Server PIVOT, или Oracle MODEL синтаксис или Postgres CROSSTAB или FILTER синтаксис.

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


Схема подходов, приведенная выше, возвращаетболее традиционная реляционная модель (отдельные столбцы со значениями).

нереляционные сопоставление атрибутов и значений в одну строку

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

В качестве элементарного примера:

 SELECT r.id
      , GROUP_CONCAT(v.title,'=',v.value ORDER BY v.name) AS vals
   FROM ( SELECT 1 AS id ) r
   LEFT
   JOIN `apj32_facileforms_subrecords` v
     ON v.record = r.id
    AND v.name in ('zipcode','firstname','lastname')
  GROUP
     BY r.id

Чтобы вернуть два столбца, что-то вроде

 id   vals
 --   --------------------------------------------------- 
  1   First Name=David,Last Name=Bacon,Zip Code=98228

Нам нужно знать, что возврат из GROUP_CONCAT ограничен group_concat_max_len байтами. И здесь мы только что сжали шарик, перенеся задачу на более позднюю обработку, чтобы проанализировать полученную строку. Если у нас есть какие-либо знаки равенства или запятые, которые появляются в значениях, это приведет к беспорядку при разборе результирующей строки. Таким образом, нам придется корректно избегать любых разделителей, которые появляются в данных, так что выражение GROUP_CONCAT станет более сложным.

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