Внутреннее объединение на логических столбцах - PullRequest
0 голосов
/ 21 мая 2018

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

1- Таблица для «основных записей», служит отправной точкой для клиентского приложения

CREATE TABLE tbRegistro (
    ID int IDENTITY(0,1) PRIMARY KEY,
    ID_ANAGRAFICA int NOT NULL,
    ID_DOCUMENTAZIONE int,
    ID_COMUNICAZIONI int,
    UTENTE nvarchar(15) NOT NULL,
    DATA_CREAZIONE datetime NOT NULL,
    LOCK bit 
    );

Пример данных:

ID          ID_ANAGRAFICA ID_DOCUMENTAZIONE ID_COMUNICAZIONI 
----------- ------------- ----------------- ---------------- 
0           1             1                 0                
1           3             3                 1                
2           5             5                 2                
3           7             7                 3                

2- Таблица «Персональные данные» увольняющихся сотрудников

CREATE TABLE tbAnagrafica (
    ID int IDENTITY(0,1) PRIMARY KEY,
    MATRICOLA nvarchar(7) NOT NULL,
    COGNOME nvarchar(50) NOT NULL,
    NOME nvarchar(50) NOT NULL,
    COD_ENTE char(5) NOT NULL,
    NOME_ENTE nvarchar(150) NOT NULL,
    UTENTE nvarchar(15) NOT NULL,
    DATA_CREAZIONE datetime NOT NULL
    );

Пример данных:

ID          MATRICOLA COGNOME           NOME                                               
----------- --------- ----------------- ----------------
1           DRTVDR    SKYWALKER         ANAKIN
3           EMPR0R    PALPATINE         SHEEV
5           NRFHRD    SOLO              HAN
7           SCARRD    SOLO              BEN

3- Таблица, содержащая сведения о каждом отдельном документе, представленномушедший в отставку aployee

CREATE TABLE tbDettaglioDoc(
    ID int IDENTITY(0,1) PRIMARY KEY,
    PROT_NUM int NOT NULL,
    PROT_DATA datetime NOT NULL,
    PRESENTE bit NOT NULL,
    INCOMPLETO bit NOT NULL,
    DISABILITATO bit NOT NULL,
    NOTE nvarchar(255),
    ID_TIPODOCUMENTO int NOT NULL,
    UTENTE nvarchar(15) NOT NULL,
    DATA_CREAZIONE datetime NOT NULL
    );

Пример данных:

ID          PROT_NUM    PROT_DATA               PRESENTE INCOMPLETO DISABILITATO ID_TIPODOCUMENTO 
----------- ----------- ----------------------- -------- ---------- ------------ ---------------- 
6           84528       2018-05-07 00:00:00.000 1        0          0            0               
7           84528       2018-05-07 00:00:00.000 1        0          0            3                
8           84528       2018-05-07 00:00:00.000 1        0          0            5               
11          84528       2018-05-07 00:00:00.000 1        0          0            9               
12          238785      2018-05-07 00:00:00.000 1        0          0            0               
13          238785      2018-05-07 00:00:00.000 1        0          0            3               
14          238785      2018-05-07 00:00:00.000 1        1          0            5               
25          51132       2018-05-07 00:00:00.000 1        0          0            4               
26          51132       2018-05-07 00:00:00.000 1        0          0            5               
28          51132       2018-05-07 00:00:00.000 1        0          0            9               
29          84350       2018-05-07 00:00:00.000 1        0          0            0               
30          84350       2018-05-07 00:00:00.000 1        1          0            3               

4- Таблица, содержащая идентификаторы всех документов для приложения в целом, сохраняя значение NULL, когда этот конкретный документ ещеотсутствует (только общие имена, показанные здесь):

CREATE TABLE tbDocumentazione(
    ID int IDENTITY(0,1) PRIMARY KEY,
    ID_ISTANZA int,
    ID_ATTIDISP int,
    ID_CEDOLINO int,
    ID_DATISENS int,
    ID_NULLAOSTA int,
    ID_INESDEBITI int,
    ID_DUM int,
    ID_MOD27 int,
    ID_CODFISC int,
    ID_DOCIDENTITA int, 
    ID_CERTMORTE int,
    ID_ATTONOTORIO int,
    UTENTE nvarchar(15) NOT NULL,
    DATA_CREAZIONE datetime NOT NULL
    );

Пример данных:

ID          ID_ISTANZA  ID_ATTIDISP ID_CEDOLINO ID_DATISENS ID_NULLAOSTA ID_INESDEBITI ID_DUM      ID_MOD27    ID_CODFISC  ID_DOCIDENTITA ID_CERTMORTE ID_ATTONOTORIO
----------- ----------- ----------- ----------- ----------- ------------ ------------- ----------- ----------- ----------- -------------- ------------ --------------
1           6           NULL        NULL        7           NULL         8             NULL        9           10          11             NULL         NULL          
3           12          NULL        NULL        13          NULL         14            NULL        NULL        15          16             NULL         NULL          
5           23          NULL        NULL        24          25           26            NULL        NULL        27          28             NULL         NULL          
7           29          NULL        NULL        30          NULL         31            NULL        32          33          34             NULL         NULL          
8           38          NULL        NULL        35          NULL         36            NULL        NULL        39          37             NULL         NULL          
9           40          NULL        NULL        41          NULL         42            NULL        43          44          45             NULL         NULL          

Я ожидал, что он выдаст что-то вроде этого (предупреждение для ботаников!)

  ID   COGNOME      NOME        MATRICOLA   ISTANZA   ATTI_DISP   CEDOLINO
+----+------------+-----------+-----------+---------+-----------+----------
  1    SKYWALKER    ANAKIN      DRTVDR      1         0           1
  2    PALPATINE    SHEEV       EMPROR      1         1           0
  3    SOLO         HAN         NRFHRD      0         1           1
  ...and so on

где "0 = отображается, когда документ не был отправлен или является неполным, но я довольно плохо знаком с T-SQL, и каждый запрос, который я пытаюсь выполнить, терпит неудачу. Так что я немного застрял. Любая помощь ДЕЙСТВИТЕЛЬНОпризнателен.

Заранее спасибо. Давиде.

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Я нашел способ получить то, что хотел:

SELECT
    tbRegistro.ID,
    tbAnagrafica.COGNOME, 
    tbAnagrafica.NOME,
    tbAnagrafica.MATRICOLA,
    (A.PRESENTE & ~A.INCOMPLETO) AS ISTANZA,
    (B.presente & ~B.incompleto) AS ATTI_DISP,
    (C.PRESENTE & ~C.INCOMPLETO) AS CEDOLINO,
    (D.PRESENTE & ~D.INCOMPLETO) AS DATISENS,
    (E.PRESENTE & ~E.INCOMPLETO) AS NULLAOSTA,
    (F.PRESENTE & ~F.INCOMPLETO) AS INESDEBITI,
    (G.PRESENTE & ~G.INCOMPLETO) AS DUM,
    (H.PRESENTE & ~H.INCOMPLETO) AS MOD27,
    (I.PRESENTE & ~I.INCOMPLETO) AS CODFISC,
    (J.PRESENTE & ~J.INCOMPLETO) AS DOCIDENTITA,
    (K.PRESENTE & ~K.INCOMPLETO) AS CERTMORTE,
    (L.PRESENTE & ~L.INCOMPLETO) AS ATTONOTORIO
FROM
    tbRegistro
    INNER JOIN tbAnagrafica ON tbRegistro.ID_ANAGRAFICA = tbAnagrafica.ID
    INNER JOIN tbDocumentazione ON tbRegistro.ID_DOCUMENTAZIONE = tbDocumentazione.ID
    FULL JOIN tbDettaglioDoc AS A ON tbDocumentazione.ID_ISTANZA = A.ID
    FULL JOIN tbDettaglioDoc AS B ON tbDocumentazione.ID_ATTIDISP = B.ID
    FULL JOIN tbDettaglioDoc AS C ON tbDocumentazione.ID_CEDOLINO = C.ID
    FULL JOIN tbDettaglioDoc AS D ON tbDocumentazione.ID_DATISENS = D.ID
    FULL JOIN tbDettaglioDoc AS E ON tbDocumentazione.ID_NULLAOSTA = E.ID
    FULL JOIN tbDettaglioDoc AS F ON tbDocumentazione.ID_INESDEBITI = F.ID
    FULL JOIN tbDettaglioDoc AS G ON tbDocumentazione.ID_DUM = G.ID
    FULL JOIN tbDettaglioDoc AS H ON tbDocumentazione.ID_MOD27 = H.ID
    FULL JOIN tbDettaglioDoc AS I ON tbDocumentazione.ID_CODFISC = I.ID
    FULL JOIN tbDettaglioDoc AS J ON tbDocumentazione.ID_DOCIDENTITA = J.ID
    FULL JOIN tbDettaglioDoc AS K ON tbDocumentazione.ID_CERTMORTE = K.ID
    FULL JOIN tbDettaglioDoc AS L ON tbDocumentazione.ID_ATTONOTORIO = L.ID
WHERE tbregistro.ID IS NOT NULL

Пример результатов:

ID          COGNOME             NOME        MATRICOLA ISTANZA ATTI_DISP CEDOLINO DATISENS NULLAOSTA INESDEBITI DUM   MOD27 CODFISC DOCIDENTITA CERTMORTE ATTONOTORIO
----------- ------------------- ----------- --------- ------- --------- -------- -------- --------- ---------- ----- ----- ------- ----------- --------- -----------
0           PALPATINE           SHEEV       EMPR0R     1       0         1        1        1         1          NULL  NULL  NULL    1           NULL      NULL
1           SKYWALKER           ANAKIN      DRTVDR     1       NULL      NULL     1        NULL      NULL       0     NULL  NULL    1           NULL      NULL

Где 1 означает правильно отправлено, 0 отправлено сошибки NULL не отправлены

0 голосов
/ 22 мая 2018

ОК. Я не вижу определенного FK, поэтому я предпочел бы, чтобы ID_TIPODOCUMENTO в tbDettaglioDoc был связан с идентификатором в tbAnagrafica, поэтому грубая идея будет выглядеть следующим образом:

SELECT P.ID, P.COGNOME, P.NOME, P.MATRICOLA,
CASE WHEN COUNT(IDoc.ID) > 0 THEN 1 ELSE 0 END AS ISTANZA,
CASE WHEN COUNT(ADoc.ID) > 0 THEN 1 ELSE 0 END AS ATTI_DISP,
CASE WHEN COUNT(CDoc.ID) > 0 THEN 1 ELSE 0 END AS CEDOLINO
FROM tbAnagrafica P
LEFT JOIN tbDettaglioDoc I ON P.ID = I.ID_TIPODOCUMENTO AND I.PRESENTE = 1 AND I.INCOMPLETO = 0
LEFT JOIN tbDocumentazione IDoc ON I.ID = IDoc.ID_ISTANZA

LEFT JOIN tbDettaglioDoc A ON P.ID = A.ID_TIPODOCUMENTO AND A.PRESENTE = 1 AND A.INCOMPLETO = 0
LEFT JOIN tbDocumentazione ADoc ON A.ID = ADoc.ID_ATTIDISP

LEFT JOIN tbDettaglioDoc C ON P.ID = C.ID_TIPODOCUMENTO AND C.PRESENTE = 1 AND C.INCOMPLETO = 0
LEFT JOIN tbDocumentazione CDoc ON C.ID = CDoc.ID_CEDOLINO
GROUP BY P.ID, P.COGNOME, P.NOME, P.MATRICOLA

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

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

Select P.ID, P.COGNOME, P.NOME, P.MATRICOLA, 0 AS ISTANZA, 0 AS ATTI_DISP, 0 AS CEDOLINO
INTO #Result from tbAnagrafica P

UPDATE R
SET ISTANZA = 1
FROM #Result R
    INNER JOIN tbDettaglioDoc I ON R.ID = I.ID_TIPODOCUMENTO
    INNER JOIN tbDocumentazione IDoc ON I.ID = IDoc.ID_ISTANZA
WHERE I.PRESENTE = 1 AND I.INCOMPLETO = 0

UPDATE R
SET ATTI_DISP = 1
...

И для последней части вы можете использовать EXISTS вместо JOIN, который в идеале должен быть лучше по производительности

UPDATE R
SET ISTANZA = 1
FROM #Result R
WHERE EXISTS(SELECT 1 FROM tbDettaglioDoc I
    INNER JOIN tbDocumentazione IDoc ON I.ID = IDoc.ID_ISTANZA
WHERE R.ID = I.ID_TIPODOCUMENTO AND I.PRESENTE = 1 AND I.INCOMPLETO = 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...