ВЫБЕРИТЕ из двух таблиц, ГДЕ разные столбцы в каждой таблице равны $id ORDER BY общий столбец (PHP/MySQL)

Я пытаюсь ВЫБРАТЬ из двух таблиц и ЗАКАЗАТЬ ПО дате (столбец, который есть у них обоих). В одной таблице (tableA) есть столбец с именем «A», а в другой таблице (tableB) есть столбец с именем «B», я использую array_key_exists(), чтобы различать их (если ключ «A» существует, я запускаю массив через FunctionA(), если ключ «B» существует, я запускаю массив через FunctionB()). Мне нужны только 20 последних (по дате) записей. Мне нужен SQL-запрос, чтобы выполнить это.

Я уже знаю, что ответ будет "если они имеют одинаковую структуру, тогда вам следует просто использовать одну таблицу", но я не хочу этого делать, потому что таблица A резко отличается от таблицы B (намного больше столбцов в таблице A), и использование одной таблицы для хранения данных приведет к МНОЖЕСТВУ пустых столбцов для записей, отформатированных для таблицы B, не говоря уже о том, что это будет очень уродливый формат таблицы из-за того, что таблица B не нуждается в большинстве столбцов таблицы A).

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

Между прочим, мне нужно ВЫБРАТЬ, ГДЕ tableA.poster_id = $id и tableB.receiver_id = $id.

РЕШЕНИЕ:

Я обновляю это на всякий случай, если кто-то еще с той же дилеммой придет. После реализации SQL-запроса, который любезно предоставил мне @Erik A. Brandstadmoen, в основном мой код получился таким:

$MySQL->SQL("SELECT * FROM
              (SELECT A.id AS id, A.date AS date, 'tableA' AS source 
                 FROM tableA A WHERE A.poster_id = $id 
                    UNION
                      SELECT B.id AS id, B.date AS date, 'tableB' AS source
                           FROM tableB B WHERE B.receiver_id = $id) AS T
                               ORDER BY T.date DESC LIMIT 0, 20");

$GetStream = array();
$i = 0;
while ($row = mysql_fetch_array($MySQL->Result))
{
    $GetStream[$i]['id'] = $row['id'];
    $GetStream[$i]['date']=$row['date'];
    $GetStream[$i]['source'] = $row['source'];
    $i++;
}

*** later on down the code ***

$i = 0;
while ($i<count($GetStream))
{
    if ($GetStream[$i]['source'] == "tableA")
    { 
        FunctionA($GetStream[$i]);
    }
    else
    {
        FunctionB($GetStream[$i]);
    }
    $i++;
}

person Lamoni    schedule 17.08.2011    source источник


Ответы (1)


Попробуйте использовать UNION:

SELECT * FROM (
SELECT A.col1 AS x, A.col2 As y, A.col3 AS date FROM tableA A
WHERE tableA.poster_id = $id
UNION 
SELECT B.colA AS x, B.colB AS y, B.colC AS date FROM  tableB B
WHERE tableB.receiver_id = $id
)
ORDER BY date DESC
LIMIT 0, 20

ИЛИ, ЕСЛИ вы хотите сохранить дубликаты между таблицей A и таблицей B, используйте вместо этого UNION ALL.

РЕДАКТИРОВАТЬ, согласно вашим комментариям, я понимаю, что вам нужен столбец, указывающий, из какой таблицы находится строка. Вы можете просто добавить статический столбец в выборку, например:

SELECT * FROM (
SELECT A.col1 AS x, A.col2 As y, A.col3 AS date, 'A' as source FROM tableA A
WHERE tableA.poster_id = $id
UNION 
SELECT B.colA AS x, B.colB AS y, B.colC AS date, 'B' as source FROM  tableB B
WHERE tableB.receiver_id = $id
)
ORDER BY date DESC
LIMIT 0, 20

Это дает вам красивую таблицу в следующей форме:

x    y    date    source
=========================
(v1) (v2) (d1)    'A'
(v3) (v4) (d2)    'B'
(v1) (v2) (d3)    'B'
(v3) (v4) (d4)    'A'

Это делает то, что вы хотите, не так ли? Немного сложно понять, чего вы действительно пытаетесь достичь с помощью этого...

person Erik A. Brandstadmoen    schedule 17.08.2011
comment
Имейте в виду, что с UNION количество/имена столбцов должны быть одинаковыми для обоих SELECT (следовательно, псевдонимы как x, как y и т. д. в этом обоих выбираются в запросах Эрика). - person Mitch Grande; 17.08.2011
comment
Я только что попробовал: SELECT * FROM ( SELECT A.id AS x, A.A AS y, A.date AS date FROM tableA A WHERE A.poster_id = $id UNION SELECT B.id AS x, B.B AS y, B.date AS date FROM tableB B WHERE B.receiver_id = $id ) AS T ORDER BY date DESC LIMIT 0, 20 Но он все еще возвращает вещи не по порядку, кстати, спасибо за ответ. - person Lamoni; 17.08.2011
comment
UNION определенно является методом, который вы хотите использовать в этой ситуации. Вам не нужен первый SELECT * FROM(), это может вызвать проблему с порядком, но я не уверен. - person Caimen; 17.08.2011
comment
Немного повозившись с этим, я упорядочил его по дате, НО по какой-то причине столбец B сохраняется в столбце A, поэтому я не могу различить два типа, большое спасибо за помощь, почти там. - person Lamoni; 17.08.2011
comment
@Caimen: Если вы не сделаете внешний выбор, вы получите таблицу A, отсортированную по дате, а затем добавленную к ней таблицу B, отсортированную по дате. Общий набор не будет сортироваться по дате. - person Erik A. Brandstadmoen; 17.08.2011
comment
@Lamoni: Что вы имеете в виду, что столбец B сохраняется в столбце A? У вас есть столбец с именем A в таблице A и таблица с именем B в таблице B? В любом случае, я не понимаю, что вы имеете в виду, говоря, что столбец B сохраняется в столбце A. Если вы имеете в виду, что все значения попадают в один столбец, в этом и есть смысл. Если вы хотите, чтобы столбцы из таблиц tableA и tableB оказались в разных столбцах результирующего набора, вам необходимо выполнить внешнее соединение таблиц. - person Erik A. Brandstadmoen; 17.08.2011
comment
Было бы неаккуратно просто создать новый логический столбец с именем type, а затем, если он окажется ложным, запустить его через функцию A, а если он верен, запустить его через функцию B? Поскольку запрос (измененный из приведенного выше примера) возвращает правильные строки и правильный порядок дат, но с неправильным именем столбца (данные таблицы B все еще сохраняются с ключом A, поэтому я не могу различать их). Таким образом, не имеет значения, что они возвращаются с одним и тем же именем столбца, потому что я могу проверить значение. (Поэтому в основном я бы использовал A.type и B.type, а не AA и BB). - person Lamoni; 17.08.2011
comment
@ Эрик А. Брандстадмоен, о да, конечно, я неправильно истолковал вопрос. - person Caimen; 17.08.2011
comment
@ Эрик, да, мне нужно, чтобы это было отдельно. Существование ключа A определяет, через какую функцию я запускаю массив. Если все возвращаемые данные используют ключ A, я не могу различить, какие данные из таблицы A, а какие из таблицы B. Короче говоря, мне нужны результаты tableA, чтобы сохранить ключ A, и результаты tableB, чтобы сохранить ключ B. - person Lamoni; 17.08.2011
comment
(Я извиняюсь за запутанный способ, которым я пытаюсь объяснить вещи, я не очень хорошо разбираюсь в номенклатуре баз данных). - person Lamoni; 17.08.2011
comment
см. мое редактирование в моем ответе. Будет ли это делать то, что вы хотите? Если нет, не могли бы вы привести пример данных, которые вы хотите вернуть из своего выбора (таблица с примерами ожидаемых результатов), и я попытаюсь настроить запрос... :) - person Erik A. Brandstadmoen; 17.08.2011
comment
Идеальный! Спасибо, сработало как шарм. Источник был ИМЕННО тем, что мне было нужно. Также в качестве бонуса я мог бы удалить свои вызовы array_key_exists(). Спасибо за ваше время, пометка как ответ. - person Lamoni; 17.08.2011
comment
Именно так я и думал... :) Удачи вашему проекту! - person Erik A. Brandstadmoen; 17.08.2011