2014-02-02 3 views
0

Я не ветеран SQL, поэтому, пожалуйста, извините меня, если это очевидно; Я изучаю.Добавление столбца соответствия в каждую строку результатов

У меня есть две таблицы в базе данных для системы приглашения на свадьбу; гостей и приглашает. Одно приглашение (приглашение) может содержать много гостей.

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

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

Может кто-нибудь пролить свет? Это можно сделать? Это чистое безумие?

Надеясь достичь:

*************************** 1. row *************************** 
     inviteID: 39 
    inviteURLSlug: thewinnetts 
       .... 
guestFirstName1: Sid 
    guestSurname1: Winnett 
guestFirstName2: Claire 
    guestSurname2: Winnett 

'приглашают' стол:

+---------------------+--------------+ 
| Field    | Type   | 
+---------------------+--------------+ 
| inviteID   | int(11)  | 
| inviteURLSlug  | varchar(64) | 
| inviteQRValue  | varchar(255) | 
| inviteQRImageURL | varchar(255) | 
| inviteAddress1  | varchar(32) | 
| inviteAddress2  | varchar(32) | 
| inviteAddress3  | varchar(32) | 
| inviteCity   | varchar(32) | 
| inviteCounty  | varchar(32) | 
| inviteCountry  | varchar(32) | 
| invitePostcode  | varchar(16) | 
| inviteDateSend  | datetime  | 
| inviteDateResponded | datetime  | 
| inviteCreated  | datetime  | 
| inviteUpdated  | timestamp | 
+---------------------+--------------+ 

'гость' стол:

+-------------------+--------------+ 
| Field    | Type   | 
+-------------------+--------------+ 
| guestID   | int(11)  | 
| inviteID   | int(11)  | 
| guestFirstName | varchar(32) | 
| guestSurname  | varchar(32) | 
| guestSide   | varchar(8) | 
| guestAttending | tinyint(1) | 
| guestEmail  | varchar(255) | 
| guestPhone  | varchar(32) | 
| guestMobile  | varchar(16) | 
| guestAddress1  | varchar(32) | 
| guestAddress2  | varchar(32) | 
| guestAddress3  | varchar(32) | 
| guestCity   | varchar(32) | 
| guestCounty  | varchar(32) | 
| guestCountry  | varchar(32) | 
| guestPostCode  | varchar(16) | 
| guestProfilePhoto | varchar(64) | 
| guestFoodVeg  | tinyint(1) | 
| guestFoodReq  | varchar(255) | 
| guestTwitter  | varchar(15) | 
| guestFacebook  | varchar(32) | 
| guestPlusone  | int(1)  | 
| guestCreated  | datetime  | 
| guestUpdated  | timestamp | 
+-------------------+--------------+ 

Failed Регистрация попытка и обрезано результаты выборки:

SELECT * FROM guest INNER JOIN invite on guest.inviteID = invite.inviteID \G 


*************************** 64. row *************************** 
      guestID: 72 
      inviteID: 39 
    guestFirstName: Claire 
     guestSurname: Winnett 
        ....... 
*************************** 65. row *************************** 
      guestID: 73 
      inviteID: 39 
    guestFirstName: Sid 
     guestSurname: Winnett 
        ....... 
+0

Можете ли вы предоставить образцы данных и желаемые результаты? –

+0

Вы пытались использовать JOIN? –

+0

@GordonLinoff Я добавил снимок INNER JOIN, который помещает каждый результат в отдельные строки, я хочу «сгруппировать» их, чтобы имена каждого пользователя появлялись в одной строке на основе идентификатора inviteID. Образец желаемых данных результата отображается вверху в исходном сообщении - нужно ли мне разъяснять что-либо для вас? – kirgy

ответ

0

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

SELECT i.*, 
    g.guestFirstName, 
    g.guestSurname 
    GROUP_CONCAT(DISTINCT g.guestFirstName, '|', g.guestSurname ORDER BY g.guestSurname DESC) AS names 
FROM invite i 
INNER JOIN guest g ON i.inviteID = g.inviteID; 

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

$names = explode(',' $queryresults['names']); 
unset($queryresults['names']); 

$i = 1; 
foreach ($names as $name) { 
    $split_name = str_split("|", $name); 
    $queryresults['guestFirstName' . $i] = $split_name[0]; 
    $queryresults['guestSurname' . $i] = $split_name[1]; 
    $i++; 
} 

Это должно дать вы, ваши желаемые результаты.

+0

Это полезно @brandonsmith, но я думаю, что havnt ясно дал понять, в чем я был, поэтому я добавил дополнительную информацию выше в разделе «Надеясь на достижение». – kirgy

+0

Спасибо за это. Я уже сделал сценарий с удивительно похожим, но я надеялся добиться того же самого с помощью только SQL (для моего собственного образования/OCD). Я рос, чувствуя, что я несколько амбициозен! – kirgy

+0

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

0

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

SELECT 
    t1.inviteID, 
    t1.guestID, 
    t1.guestFirstName, 
    t1.guestSurname, 
    t2.guestFirstName AS guestFirstName2, 
    t2.guestSurname AS guestSurname2 
FROM 
    guests as t1 
LEFT OUTER JOIN 
    guests as t2 
ON t1.inviteID = t2.inviteID 
AND t1.guestID <> t2.guestID 
WHERE 
t1.guestID = (select min(t3.guestID) from guests as t3 where t3.inviteID = t1.inviteID) 
; 

В таблице guests используется дважды, один раз для обеспечения первого гостя на каждом пригласить, а второй раз, используя LEFT OUTER JOIN, чтобы обеспечить второй. LEFT OUTER гарантирует, что вы все равно получите первое, даже если нет второго. Остальные критерии заключаются в том, что вы не присоединяетесь к строке для себя, и вы выводите только первые, с секундами (а не наоборот).

Here is a sample fiddle (в MySQL)

0

Это что-то вроде этого, что вы ищете?

Обновлено после вашего комментария.

SELECT GROUP_CONCAT(DISTINCT `guest`.`guestFirstName`,`guest`.`guestSurname`, `invite`.`inviteURLSlug`) FROM `guest` 
LEFT JOIN `invite` ON `invite`.`inviteID` = `guest`.`inviteID` 
WHERE `invite`.`inviteID` = 5 

Я просто сделал два простых таблиц с минимальной информацией для тестирования, но легко расширяемой к тому, что у вас есть/хотите.

У вас появятся несколько полей, так как количество строк будет связано с количеством гостей.

+0

Это почти то, о чем я беспокоился, чтобы объяснить - спасибо за то, что он со мной. Последним препятствием (если это возможно) является повторение этого для каждого идентификатора приглашения, то есть: «WHERE invite.inviteID = 1; ... WHERE invite.inviteID = 2; ... WHERE invite.inviteID = 3;» и так на. Это возможно? – kirgy

+1

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

Смежные вопросы