Пожалуйста, помогите преобразовать Tsql "неявные объединения" в явные - PullRequest
4 голосов
/ 31 июля 2010

Извините, я в значительной степени нуб SQL. Это должно работать в MSFT SQL, Oracle, а также Sybase. В следующем фрагменте мне нужно изменить inner join между IJ и KL на IJ.PO_id = KL.PO_id на left join также на IJ.PO_id = KL.PO_id. Итак, я считаю, что я должен заново учесть это. Ну, неявные объединения не самые читаемые, по крайней мере, в глазах моего сотрудника. Думаю, я соглашусь, пока не разовью свой вкус. Извините, я исказил имена таблиц и полей на всякий случай.

/* @IJ_id is an input stored proc patrameter. */
from AB, 
     CD,
     EF,
     GH,
     IJ,
     KL
where
    EF.EF_id = IJ.EF_id and
    IJ.EF_id = AB.EF_id and
    EF.ZY_id = IJ.ZY_id and
    IJ.ZY_id = AB.ZY_id and
    IJ.IJ_id = AB.IJ_id and
    IJ.IJ_id = @IJ_id and
    EF.XW_id = GH.GH_id and
    AB.VU_code = CD.VU_code and
    IJ.TS > 0 and
    IJ.RQ = 0 and
    EF.RQ = 0 and
    AB.RQ = 0 and
    IJ.PO_id = KL.PO_id;

Теперь моя трудность заключается в том, что в предложении where много чего происходит. Вещи, которые не похожи на a.b = c.d, останутся в предложении where, но не все вещи, которые выглядят как a.b = c.d, легко преобразовать в явное соединение. Трудная часть состоит в том, что в идеале условия должны быть между соседями - AB+CD, CD+EF, EF+GH, GH+IJ, IJ+KL, но они сейчас не настолько организованы. Я мог бы переупорядочить некоторые, но в конечном итоге я не хочу забывать свою цель: я хочу, чтобы новый запрос был не медленнее, и я хочу, чтобы новый запрос был не менее читабельным. Кажется, мне лучше взломать только ту часть, которую мне нужно изменить, и оставить ее в основном той же самой. Я не уверен, смогу ли я это сделать.

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

Ответы [ 3 ]

3 голосов
/ 31 июля 2010

Я думаю, что это должно быть примерно так:

FROM AB
JOIN CD ON AB.VU_code = CD.VU_code
JOIN IJ ON IJ.EF_id = AB.EF_id AND IJ.ZY_id = AB.ZY_id AND IJ.IJ_id = AB.IJ_id
JOIN EF ON EF.EF_id = IJ.EF_id AND EF.ZY_id = IJ.ZY_id
JOIN GH ON EF.XW_id = GH.GH_id
JOIN KL ON IJ.PO_id = KL.PO_id
WHERE
    IJ.IJ_id = @IJ_id AND
    IJ.TS > 0 AND
    IJ.RQ = 0 AND
    EF.RQ = 0 AND
    AB.RQ = 0

Я пытался расположить таблицы так, чтобы выполнялись следующие правила:

  • В каждом условии объединения упоминается новая таблица, к которой оно присоединяется с одной стороны.
  • Ни одна таблица не упоминается в условии соединения, если эта таблица еще не была объединена.
  • Условия, в которых один из операндов является константой, остаются в качестве условия WHERE.

Последнее правило является сложным - по вашим искаженным именам невозможно определить, должно ли условие быть частью объединения или частью предложения where. Оба дадут один и тот же результат для внутреннего соединения. То, должно ли условие быть частью соединения или частью предложения where, зависит от семантики отношений между таблицами.

Вам необходимо учитывать каждое условие в каждом конкретном случае:

  • Определяет ли это отношение между двумя таблицами? Поместите это в СОЕДИНЕНИЕ.
  • Это фильтр по результатам? Поместите это в предложение WHERE.

Некоторые рекомендации:

  • Условие, включающее параметр от пользователя, вряд ли должно быть чем-то, что следует переместить в объединение.
  • Неравенства обычно не встречаются в условиях соединения.
1 голос
/ 31 июля 2010

Использование:

 FROM AB t1
 JOIN CD t2 ON t2.VU_code = t1.VU_code
 JOIN GH t4 ON t4.gh_id = t3.xw_id
 JOIN IJ t5 ON t5.ZY_id = t1.ZY_id
           AND t5.IJ_id = t1.IJ_id
           AND t5.EF_id = t1.EF_id 
           AND t5.IJ_id = @IJ_id 
           AND t5.TS > 0 
           AND t5.RQ = 0 
 JOIN EF t3 ON t3.ef_id = t5.ef_id
           AND t3.zy_id = t5.zy_id
           AND t3.RQ = 0
 JOIN KL t6 ON t6.po_id = t5.po_id -- Add LEFT before JOIN for LEFT JOIN
WHERE ab.qu = 0

Они имеют псевдоним в последовательности исходного синтаксиса ANSI-89, но порядок корректируется из-за ссылки на псевдоним - не может ссылаться на псевдоним таблицы, пока он не был определен.

Это синтаксис ANSI-92 JOIN - никакого выигрыша в производительности нет, но это означает, что синтаксис OUTER join является согласованным. Просто добавьте LEFT перед "JOIN KL ...", чтобы превратить это в LEFT JOIN.

1 голос
/ 31 июля 2010

Это не может быть менее читабельным, чем пример, который вы дали ...

from AB a
join CD c on a.VU_Code = c.VU_Code
join EF e on a.EF_id = e.EF_id and e.RQ = 0
join GH g on e.XW_id = g.GH_id
join IJ i on a.IJ_id = i.IJ_id and e.EF_id = i.EF_id
         and a.EF_id = i.EF_id and e.ZY_id = i.ZY_id
         and a.ZY_id = i.ZY_id and i.TS > 0 and i.RQ = 0
LEFT join KL k on i.PO_id = k.PO_id
where 
    i.IJ_id = @IJ_id and 
    a.RQ = 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...