Как преобразовать строки в столбцы в mySQL [duplicate]

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

http://docs.oracle.com/javase/7/docs/api/java/ языки / Thread.html

126
задан slier 19 September 2016 в 07:03
поделиться

10 ответов

использовать подзапрос

SELECT  hostid, 
    (SELECT VALUE FROM TableTest WHERE ITEMNAME='A' AND hostid = t1.hostid) AS A,
    (SELECT VALUE FROM TableTest WHERE ITEMNAME='B' AND hostid = t1.hostid) AS B,
    (SELECT VALUE FROM TableTest WHERE ITEMNAME='C' AND hostid = t1.hostid) AS C
FROM TableTest AS T1
GROUP BY hostid

, но это будет проблемой, если sub-запрос, полученный больше, чем строка, использует дополнительную агрегированную функцию в подзапросе

7
ответ дан Agung Sagita 16 August 2018 в 04:48
поделиться

Я отредактировал ответ Agung Sagita из подзапроса, чтобы присоединиться. Я не уверен, сколько разницы между этими двумя способами, но только для другой ссылки.

SELECT  hostid, T2.VALUE AS A, T3.VALUE AS B, T4.VALUE AS C
FROM TableTest AS T1
LEFT JOIN TableTest T2 ON T2.hostid=T1.hostid AND T2.ITEMNAME='A'
LEFT JOIN TableTest T3 ON T3.hostid=T1.hostid AND T3.ITEMNAME='B'
LEFT JOIN TableTest T4 ON T4.hostid=T1.hostid AND T4.ITEMNAME='C'
10
ответ дан Community 16 August 2018 в 04:48
поделиться
  • 1
    Возможно, это может быть более быстрое решение. – jave.web 7 April 2016 в 13:30

Мое решение:

select h.hostid, sum(ifnull(h.A,0)) as A, sum(ifnull(h.B,0)) as B, sum(ifnull(h.C,0)) as  C from (
select
hostid,
case when itemName = 'A' then itemvalue end as A,
case when itemName = 'B' then itemvalue end as B,
case when itemName = 'C' then itemvalue end as C
  from history 
) h group by hostid

Получает ожидаемые результаты в представленном случае.

1
ответ дан iCodez 16 August 2018 в 04:48
поделиться

Это не точный ответ, который вы ищете, но это решение, которое мне нужно для моего проекта, и надеюсь, что это поможет кому-то. Это будет перечислять от 1 до n элементов строки, разделенных запятыми. Group_Concat делает это возможным в MySQL.

select
cemetery.cemetery_id as "Cemetery_ID",
GROUP_CONCAT(distinct(names.name)) as "Cemetery_Name",
cemetery.latitude as Latitude,
cemetery.longitude as Longitude,
c.Contact_Info,
d.Direction_Type,
d.Directions

    from cemetery
    left join cemetery_names on cemetery.cemetery_id = cemetery_names.cemetery_id 
    left join names on cemetery_names.name_id = names.name_id 
    left join cemetery_contact on cemetery.cemetery_id = cemetery_contact.cemetery_id 

    left join 
    (
        select 
            cemetery_contact.cemetery_id as cID,
            group_concat(contacts.name, char(32), phone.number) as Contact_Info

                from cemetery_contact
                left join contacts on cemetery_contact.contact_id = contacts.contact_id 
                left join phone on cemetery_contact.contact_id = phone.contact_id 

            group by cID
    )
    as c on c.cID = cemetery.cemetery_id


    left join
    (
        select 
            cemetery_id as dID, 
            group_concat(direction_type.direction_type) as Direction_Type,
            group_concat(directions.value , char(13), char(9)) as Directions

                from directions
                left join direction_type on directions.type = direction_type.direction_type_id

            group by dID


    )
    as d on d.dID  = cemetery.cemetery_id

group by Cemetery_ID

Это кладбище имеет два общих имени, поэтому имена перечислены в разных строках, соединенных одним идентификатором, но с двумя идентификаторами имен, и запрос производит что-то вроде этого & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; CemeteryID & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; Cemetery_Name & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; Appleton, Sulpher Springs & nbsp; & nbsp; 35.4276242832293

1
ответ дан James Humphrey 16 August 2018 в 04:48
поделиться

Я делаю это в Group By hostId, тогда он будет показывать только первую строку со значениями, такими как:

A   B  C
1  10
2      3
3
ответ дан Johan 16 August 2018 в 04:48
поделиться

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

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

SELECT distinct concat('<th>',itemname,'</th>') as column_name_table_header FROM history order by 1;

SELECT
     hostid
    ,(case when itemname = (select distinct itemname from history a order by 1 limit 0,1) then itemvalue else '' end) as col1
    ,(case when itemname = (select distinct itemname from history a order by 1 limit 1,1) then itemvalue else '' end) as col2
    ,(case when itemname = (select distinct itemname from history a order by 1 limit 2,1) then itemvalue else '' end) as col3
    ,(case when itemname = (select distinct itemname from history a order by 1 limit 3,1) then itemvalue else '' end) as col4
FROM history order by 1;

Вы также можете суммировать его:

SELECT
     hostid
    ,sum(case when itemname = (select distinct itemname from history a order by 1 limit 0,1) then itemvalue end) as A
    ,sum(case when itemname = (select distinct itemname from history a order by 1 limit 1,1) then itemvalue end) as B
    ,sum(case when itemname = (select distinct itemname from history a order by 1 limit 2,1) then itemvalue end) as C
FROM history group by hostid order by 1;
+--------+------+------+------+
| hostid | A    | B    | C    |
+--------+------+------+------+
|      1 |   10 |    3 | NULL |
|      2 |    9 | NULL |   40 |
+--------+------+------+------+

Результаты RexTester :

http://rextester.com/ZSWKS28923

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

1
ответ дан lynx_74 16 August 2018 в 04:48
поделиться

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


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

select * from history;

+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
|      1 | A        |        10 |
|      1 | B        |         3 |
|      2 | A        |         9 |
|      2 | C        |        40 |
+--------+----------+-----------+

Это будет нашей целью, красивой сводной таблицей:

select * from history_itemvalue_pivot;

+--------+------+------+------+
| hostid | A    | B    | C    |
+--------+------+------+------+
|      1 |   10 |    3 |    0 |
|      2 |    9 |    0 |   40 |
+--------+------+------+------+

Значения в столбце history.hostid станут значениями y в сводной таблице. Значения в столбце history.itemname станут x-значениями (по очевидным причинам).


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

  1. выберите интересующие столбцы, т. е. значения y и значения x
  2. расширят базовую таблицу дополнительными столбцами - один для каждая группа x-значение
  3. и агрегировать расширенную таблицу - по одной группе для каждого значения y
  4. (необязательно) префикс агрегированной таблицы

Давайте применим эти шаги к вашей проблеме и посмотрим, что получим:

Шаг 1: выберите интересующие столбцы. В желаемом результате hostid предоставляет значения y, а itemname предоставляет значения x.

Шаг 2: расширьте базовую таблицу дополнительными столбцами. Обычно нам нужен один столбец за x-значение. Напомним, что наш столбец x-value itemname:

create view history_extended as (
  select
    history.*,
    case when itemname = "A" then itemvalue end as A,
    case when itemname = "B" then itemvalue end as B,
    case when itemname = "C" then itemvalue end as C
  from history
);

select * from history_extended;

+--------+----------+-----------+------+------+------+
| hostid | itemname | itemvalue | A    | B    | C    |
+--------+----------+-----------+------+------+------+
|      1 | A        |        10 |   10 | NULL | NULL |
|      1 | B        |         3 | NULL |    3 | NULL |
|      2 | A        |         9 |    9 | NULL | NULL |
|      2 | C        |        40 | NULL | NULL |   40 |
+--------+----------+-----------+------+------+------+

Обратите внимание, что мы не изменили количество строк - мы просто добавили дополнительные столбцы. Также обратите внимание на шаблон NULL s - строка с itemname = "A" имеет ненулевое значение для нового столбца A и нулевые значения для других новых столбцов.

Шаг 3: группа и заполнить расширенную таблицу. Нам нужно group by hostid, так как он предоставляет значения y:

create view history_itemvalue_pivot as (
  select
    hostid,
    sum(A) as A,
    sum(B) as B,
    sum(C) as C
  from history_extended
  group by hostid
);

select * from history_itemvalue_pivot;

+--------+------+------+------+
| hostid | A    | B    | C    |
+--------+------+------+------+
|      1 |   10 |    3 | NULL |
|      2 |    9 | NULL |   40 |
+--------+------+------+------+

(Обратите внимание, что теперь мы имеем одну строку на y-значение.) Хорошо, Ре почти там! Нам просто нужно избавиться от этих уродливых NULL s.

Шаг 4: приглушить. Мы просто заменим любые нулевые значения нулями, поэтому результат будет приятнее посмотреть:

create view history_itemvalue_pivot_pretty as (
  select 
    hostid, 
    coalesce(A, 0) as A, 
    coalesce(B, 0) as B, 
    coalesce(C, 0) as C 
  from history_itemvalue_pivot 
);

select * from history_itemvalue_pivot_pretty;

+--------+------+------+------+
| hostid | A    | B    | C    |
+--------+------+------+------+
|      1 |   10 |    3 |    0 |
|      2 |    9 |    0 |   40 |
+--------+------+------+------+

И мы закончили - мы создали красивую, симпатичную сводную таблицу, используя MySQL.


Соображения при применении этой процедуры:

  • какое значение использовать в дополнительных столбцах. Я использовал itemvalue в этом примере
  • , какое «нейтральное» значение использовать в дополнительных столбцах. Я использовал NULL, но также может быть 0 или "", в зависимости от вашей точной ситуации
  • , какую функцию агрегата использовать при группировке. Я использовал sum, но часто используются count и max (max часто используется при создании однострочных «объектов», которые были распределены по многим строкам)
  • с использованием нескольких столбцы для значений y. Это решение не ограничивается использованием одного столбца для значений y - просто подключите дополнительные столбцы к предложению group by (и не забудьте его select)

Известные ограничения:

  • это решение не позволяет использовать n столбцов в сводной таблице - каждая сводная колонка должна быть добавлена ​​вручную при расширении базовой таблицы. Таким образом, для 5 или 10 значений x это решение является приятным. На 100, не очень приятно. Существуют некоторые решения с хранимыми процедурами, генерирующими запрос, но они уродливы и труднодоступны. В настоящее время я не знаю, как правильно решить эту проблему, когда в сводной таблице должно быть много столбцов.
191
ответ дан Matt Fenwick 16 August 2018 в 04:48
поделиться
  • 1
    +1 Это, безусловно, лучшее / самое четкое объяснение сводных таблиц / кросс-вкладок в MySQL, которые я видел – cameron.bracken 21 August 2012 в 17:24
  • 2
    Отличное объяснение, спасибо. Шаг 4 можно объединить в шаг 3, используя IFNULL (сумма (A), 0) AS A, давая вам тот же результат, но без необходимости создания еще одной таблицы – nealio82 20 March 2013 в 12:33
  • 3
    Лучшее объяснение когда-либо. Потрясающие – Matarishvan 27 February 2015 в 08:05
  • 4
    Это было самое удивительное решение для точки опоры, но мне просто любопытно, если в столбце itemname, которое образует ось x, имеет несколько значений, например, здесь мы имеем только три значения: A, B, C. Если эти значения получаются до A, B, C, D, E, AB, BC, AC, AD, H ..... n. то в этом случае было бы решением. – Deepesh 24 February 2016 в 12:45
  • 5
    это должен быть действительно принятый ответ здесь. Это более подробно, полезно и объясняет, как понять это, а не просто ссылаться на какую-то статью, например, – EdgeCaseBerg 6 June 2016 в 16:43

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

SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'ifnull(SUM(case when itemname = ''',
      itemname,
      ''' then itemvalue end),0) AS `',
      itemname, '`'
    )
  ) INTO @sql
FROM
  history;
SET @sql = CONCAT('SELECT hostid, ', @sql, ' 
                  FROM history 
                   GROUP BY hostid');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

FIDDLE Добавлены некоторые дополнительные значения для см. в нем

GROUP_CONCAT имеет значение по умолчанию 1000, поэтому, если у вас есть действительно большой запрос, измените этот параметр перед его запуском

SET SESSION group_concat_max_len = 1000000;

Тест:

DROP TABLE IF EXISTS history;
CREATE TABLE history
(hostid INT,
itemname VARCHAR(5),
itemvalue INT);

INSERT INTO history VALUES(1,'A',10),(1,'B',3),(2,'A',9),
(2,'C',40),(2,'D',5),
(3,'A',14),(3,'B',67),(3,'D',8);

  hostid    A     B     C      D
    1     10      3     0      0
    2     9       0    40      5
    3     14     67     0      8
18
ответ дан Mihai 16 August 2018 в 04:48
поделиться

Воспользовавшись идеей Мэтта Фенвика, которая помогла мне решить проблему (большое спасибо), давайте уменьшим ее только до одного запроса:

select
    history.*,
    coalesce(sum(case when itemname = "A" then itemvalue end), 0) as A,
    coalesce(sum(case when itemname = "B" then itemvalue end), 0) as B,
    coalesce(sum(case when itemname = "C" then itemvalue end), 0) as C
from history
group by hostid
20
ответ дан Nik Reiman 16 August 2018 в 04:48
поделиться
  • 1
    Спасибо Nik за исправления, мне нужны английские классы :) – jalber 22 October 2012 в 12:50
SELECT 
    hostid, 
    sum( if( itemname = 'A', itemvalue, 0 ) ) AS A,  
    sum( if( itemname = 'B', itemvalue, 0 ) ) AS B, 
    sum( if( itemname = 'C', itemvalue, 0 ) ) AS C 
FROM 
    bob 
GROUP BY 
    hostid;
30
ответ дан shA.t 16 August 2018 в 04:48
поделиться
Другие вопросы по тегам:

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