2015-09-04 4 views
-1

Обратите внимание, что я знаю, что это должно быть что-то простое и, вероятно, очевидное - я просто не вижу его ... Как указано, знаете ли вы, почему этот SQL-запрос возвращает пустой список при выполнении на SQL Server (через SQL Server Management Studio), при условии, что ЕСТЬ ДАННЫЕ В СООТВЕТСТВУЮЩИХ ТАБЛИЦЕ И ВСЕ ПАРАМЕТРЫ ЗАПРОСА УСТАНОВЛЕНЫ ПРАВИЛЬНО?Почему SQL Server SQL-запрос возвращает пустой список?

Этот вопрос связан с моим другим вопросом (Does anyone know why JPQL query on a view with SQL Server does not work? 'GetResultList' always returns empty list), но на данном этапе он фактически превращается в отдельную тему, поэтому я разместил его здесь. Вот запрос:

SELECT t1.Id, 
     t2.IdTransiti, 
     t1.CodiceCaricoPericoloso, 
     t1.Confidenza, 
     t1.Istante, 
     t1.IstanteRicezione, 
     t2.SQLServer_latitude, 
     t2.SQLServer_longitude, 
     t1.Partizione, 
     t1.Targa, 
     t1.TargaSecondaria, 
     t1.UtmcInstanceId, 
     t1.VelocitaStimata, 
     t1.IdColore, 
     t1.IdCorsia, 
     t1.IdMarca, 
     t1.IdModello, 
     t1.IdNazionalita, 
     t1.IdSerie, 
     t1.IdTipologiaVeicolo 
    FROM dbo.TransitiView t1 
    LEFT OUTER JOIN Serie t0 
     ON (t0.Id = t1.IdSerie) 
    LEFT OUTER JOIN dbo.Colori t3 
     ON (t3.Id = t1.IdColore) 
    LEFT OUTER JOIN Modelli t4 
     ON (t4.Id = t1.IdModello) 
    LEFT OUTER JOIN Marche t5 
     ON (t5.Id = t1.IdMarca), 
    TransitiPunti t2, 
    Corsie t6 
    WHERE ((((((t6.Attiva = 1) 
        AND (t1.Istante BETWEEN '2015-09-03 00:16:50.693' 
             AND '2015-09-03 23:16:50.693')) 
       AND ((t1.Partizione = 0) OR (t1.Partizione = 6))) 
       AND (t1.IdCorsia = 1)) 
      AND (t2.IdTransiti = t1.Id)) 
      AND (t6.Id = t1.IdCorsia)) 
ORDER BY t1.Istante DESC 

EDIT:

Благодаря Russ ответа теперь я знаю, что происходит - SQL Server не любит пустые записи в внутренних соединениях - ODD !! Возможно, кто-то из вас знает, как и можно ли сделать внутренние соединения SQL Server «LIKE», где записи могут отсутствовать в соответствующих столбцах в связанных таблицах? Или ... По крайней мере, как заставить это работать для этого конкретного запроса?

Я думал, что сделаю это: ... ON (t2.IdTransiti = t1.Id или t2.IdTransiti - null), но это НЕ подходит для SQL Server. это не помогло :(

BONUS QUESTION: Любая идея, почему это нормально для MySQL, но не для SQL Server, когда таблицы, соединенные через внутренние соединения, могут быть пустыми? Почему это должно быть НЕ нормально в первую очередь?


EDIT:

оТВЕТ нА ПРОБЛЕМЫ:.. Благодаря Russ - я в основном получил его - это только мое замешательство и ничего более Пожалуйста, прочтите комментарии по принятому ответу Все стеблями из того, что я забыл, не было ow, что @SecondaryTable аннотация в JPA переводится во внутреннее соединение, а затем двойная путаница - по моему пренебрежению ЧТО ОЧЕНЬ ВНУТРЕННЕЕ ОБЪЕДИНЕНИЕ ОЖИДАЕТСЯ ЗНАЧЕНИЯМИ В ОБЩИХ ТАБЛИЦЕ !!!

Спасибо всем за их усилия, и я думаю, мне нужно немного подумать, прежде чем говорить о вещах в следующий раз :).

+3

Не следует смешивать Явный синтаксис и старые неявный присоединиться !!! Слишком легко сделать ошибки - используйте только новый, явный синтаксис соединения! – jarlh

+2

Переместите условия t2 и т. Д. Из WHERE в ON, чтобы получить истинное значение LEFT JOIN. (Как сейчас, он выполняет как регулярное внутреннее соединение ...) – jarlh

+0

@jarhl Спасибо, Jahrl! Но что интересно, этот запрос на самом деле автогенерируется драйвером SQL sqljdbc4.jar из моего проекта, я бы ожидал, что он не должен ошибаться? Вы знаете, что может быть причиной здесь? Кроме того, знаете ли вы, если в этом запросе есть что-то не так, потому что он выполняется без ошибок, за исключением того, что он просто возвращает пустой список. – Pawel

ответ

-1

Экспобрекетинг кажется необычным, вы можете попробовать заменить текущий ИНЕКЕ с этим:

WHERE t6.Attiva = 1 
AND (t1.Istante BETWEEN '2015-09-03 00:16:50.693' AND '2015-09-03 23:16:50.693') 
AND (t1.Partizione = 0 OR t1.Partizione = 6) 
AND t1.IdCorsia = 1 
AND t2.IdTransiti = t1.Id 
AND t6.Id = t1.IdCorsia 
ORDER BY t1.Istante DESC 

Если таблица transitipunti пуста, попробуйте следующее:

SELECT t1.Id, 
    t1.CodiceCaricoPericoloso, 
    t1.Confidenza, 
    t1.Istante, 
    t1.IstanteRicezione, 
    t1.Partizione, 
    t1.Targa, 
    t1.TargaSecondaria, 
    t1.UtmcInstanceId, 
    t1.VelocitaStimata, 
    t1.IdColore, 
    t1.IdCorsia, 
    t1.IdMarca, 
    t1.IdModello, 
    t1.IdNazionalita, 
    t1.IdSerie, 
    t1.IdTipologiaVeicolo 
FROM dbo.TransitiView t1 
LEFT OUTER JOIN Serie t0 
    ON (t0.Id = t1.IdSerie) 
LEFT OUTER JOIN dbo.Colori t3 
    ON (t3.Id = t1.IdColore) 
LEFT OUTER JOIN Modelli t4 
    ON (t4.Id = t1.IdModello) 
LEFT OUTER JOIN Marche t5 
    ON (t5.Id = t1.IdMarca), 
Corsie t6 
WHERE t6.Attiva = 1 
AND (t1.Istante BETWEEN '2015-09-03 00:16:50.693' AND '2015-09-03 23:16:50.693') 
AND (t1.Partizione = 0 OR t1.Partizione = 6) 
AND t1.IdCorsia = 1 
AND t6.Id = t1.IdCorsia 
ORDER BY t1.Istante DESC 

Null дружеское Соединение слева в SQL Server:

create table abc 
(
a int, 
b int, 
c int 
) 

create table def 
(
d int, 
e int, 
f int 
) 

insert into abc values (1,2,3) 

select * from abc left join def on abc.a = def.d or def.d = null 
+0

Спасибо, но нет разницы. – Pawel

+0

Спасибо! Перхабс. Я должен на самом деле отредактировать свой вопрос - он работает без внутренних объединений, я знал это на самом деле прежде, чем БЛАГОДАРЯ ВАС, я действительно понял, почему. Это потому, что SQL Server кажется странным и не переносит пустые записи! Вы знаете, есть ли способ сделать SQL Server «LIKE» внутренними соединениями, где таблица пуста? Кажется странным, что MySQL Server может обрабатывать эти ситуации, в то время как SQL Server не может. Это случилось с тобой раньше? Спасибо за помощь! – Pawel

+0

Я всегда отношусь к внутренним объединениям, так как обязательно требую, чтобы некоторые данные дали какой-либо набор результатов. Я бы начал (и я не говорю, что я пробовал это), думая о том, как поставить «или isnull 'в параметре ON ...? – russ

0

Если вы считаете, что в таблице [TransitiPunti] нет записей, то да, что остановит любой запрос, используя INNER JOIN в этом запросе, из создания строк. Примечание. В вашем существующем запросе используется INNER JOIN на этой таблице (к сожалению, он использует старомодный синтаксис, но это внутреннее соединение).

Я предлагаю вам протестировать «постепенно», чтобы вы могли решить проблему. «Начните с малого», попробуйте, если успешно добавьте элементы по одному и повторите попытку.

Как только вы прекратите получать результаты, вы знаете, что последний элемент был добавлен, и это будет тот элемент, который вызывает проблему.

Здесь, например, есть 3 вопроса.Только

/* одна таблица (t1) */

SELECT 
     t1.Id 
    , t1.CodiceCaricoPericoloso 
    , t1.Confidenza 
    , t1.Istante 
    , t1.IstanteRicezione 
    , t1.Partizione 
    , t1.Targa 
    , t1.TargaSecondaria 
    , t1.UtmcInstanceId 
    , t1.VelocitaStimata 
    , t1.IdColore 
    , t1.IdCorsia 
    , t1.IdMarca 
    , t1.IdModello 
    , t1.IdNazionalita 
    , t1.IdSerie 
    , t1.IdTipologiaVeicolo 
FROM dbo.TransitiView t1 
WHERE t1.Istante BETWEEN '2015-09-03 00:16:50.693' AND '2015-09-03 23:16:50.693' 
     AND (t1.Partizione = 0 OR t1.Partizione = 6) 
     AND t1.IdCorsia = 1 
ORDER BY t1.Istante DESC 
; 

/* две таблицы (t1 & t6) */

SELECT 
     t1.Id 
    , t1.CodiceCaricoPericoloso 
    , t1.Confidenza 
    , t1.Istante 
    , t1.IstanteRicezione 
    , t1.Partizione 
    , t1.Targa 
    , t1.TargaSecondaria 
    , t1.UtmcInstanceId 
    , t1.VelocitaStimata 
    , t1.IdColore 
    , t1.IdCorsia 
    , t1.IdMarca 
    , t1.IdModello 
    , t1.IdNazionalita 
    , t1.IdSerie 
    , t1.IdTipologiaVeicolo 
FROM dbo.TransitiView t1 
     INNER JOIN Corsie t6 ON t6.Id = t1.IdCorsia 
WHERE t6.Attiva = 1 
     AND t1.Istante BETWEEN '2015-09-03 00:16:50.693' AND '2015-09-03 23:16:50.693' 
     AND (t1.Partizione = 0 OR t1.Partizione = 6) 
     AND t1.IdCorsia = 1 
ORDER BY t1.Istante DESC 
; 

/* три таблицы t1, t2, t6 */

SELECT 
     t1.Id 
    , t2.IdTransiti 
    , t1.CodiceCaricoPericoloso 
    , t1.Confidenza 
    , t1.Istante 
    , t1.IstanteRicezione 
    , t2.SQLServer_latitude 
    , t2.SQLServer_longitude 
    , t1.Partizione 
    , t1.Targa 
    , t1.TargaSecondaria 
    , t1.UtmcInstanceId 
    , t1.VelocitaStimata 
    , t1.IdColore 
    , t1.IdCorsia 
    , t1.IdMarca 
    , t1.IdModello 
    , t1.IdNazionalita 
    , t1.IdSerie 
    , t1.IdTipologiaVeicolo 
FROM dbo.TransitiView t1 
     INNER JOIN TransitiPunti t2 ON t2.IdTransiti = t1.Id 
     INNER JOIN Corsie t6 ON t6.Id = t1.IdCorsia 
WHERE t6.Attiva = 1 
     AND t1.Istante BETWEEN '2015-09-03 00:16:50.693' AND '2015-09-03 23:16:50.693' 
     AND (t1.Partizione = 0 OR t1.Partizione = 6) 
     AND t1.IdCorsia = 1 
ORDER BY t1.Istante DESC 

НИКОГДА не используйте смесь старого синтаксиса соединения с (лучше) явным соединением ANSI.

Мне также не нравятся лишние круглые скобки, я считаю, что они путают, а не помогают.

SELECT 
     t1.Id 
    , t2.IdTransiti 
    , t1.CodiceCaricoPericoloso 
    , t1.Confidenza 
    , t1.Istante 
    , t1.IstanteRicezione 
    , t2.SQLServer_latitude 
    , t2.SQLServer_longitude 
    , t1.Partizione 
    , t1.Targa 
    , t1.TargaSecondaria 
    , t1.UtmcInstanceId 
    , t1.VelocitaStimata 
    , t1.IdColore 
    , t1.IdCorsia 
    , t1.IdMarca 
    , t1.IdModello 
    , t1.IdNazionalita 
    , t1.IdSerie 
    , t1.IdTipologiaVeicolo 
FROM dbo.TransitiView t1 
     /* 
     LEFT OUTER JOIN Serie t0 ON t0.Id = t1.IdSerie 
     LEFT OUTER JOIN dbo.Colori t3 ON t3.Id = t1.IdColore 
     LEFT OUTER JOIN Modelli t4 ON t4.Id = t1.IdModello 
     LEFT OUTER JOIN Marche t5 ON t5.Id = t1.IdMarca 
     */ 
     INNER JOIN TransitiPunti t2 ON t2.IdTransiti = t1.Id 
     INNER JOIN Corsie t6 ON t6.Id = t1.IdCorsia 
WHERE t6.Attiva = 1 
     AND t1.Istante BETWEEN '2015-09-03 00:16:50.693' AND '2015-09-03 23:16:50.693' 
     AND (t1.Partizione = 0 OR t1.Partizione = 6) 
     AND t1.IdCorsia = 1 
ORDER BY t1.Istante DESC 

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

кстати это:

AND (t1.Partizione = 0 OR t1.Partizione = 6) 

может быть изменен на:

AND t1.Partizione IN (0,6) 
+0

Спасибо, сделали это - поверьте мне или нет, но ваш запрос по-прежнему возвращает пустой список .... – Pawel

+0

Да, в таблице есть данные. Это как раз View, а не таблица, но это не имеет значения, правильно? Например, запрос выбирает * из dbo.TransitiView, где dbo.TransitiView.Partizione = 0 AND ... работает корректно и возвращает данные. – Pawel

+0

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

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