Создать недостающие строки с помощью JOIN / CROSS JOIN - PullRequest
0 голосов
/ 02 марта 2020

У меня есть 3 таблицы, которые используются для заполнения Dynami c из значения.

Таблица представлена ​​схемой ниже.

enter image description here

Пользователь может добавить столько строк, сколько возможно, и строки будут показаны конечному пользователю по шаблону из таблицы FormField.

Данные, сохраненные в FormValues, предназначены только для ненулевых значений и любых значений, которые пропущенные не сохраняются.

Теперь проблема в том, что я должен создать отчет, как ожидается ниже.

enter image description here

Я пробовал различные комбинации of join / cross join, но ни один из них не работает должным образом.

Я могу добиться этого в C# с помощью циклов, но не могу сделать то же самое с помощью SQL Server.

Скрипт прилагается для БД

USE [SampleDb]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[FormTemplate](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_FormTemplate] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)
) ON [PRIMARY]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[FormField](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [FormId] [int] NOT NULL,
    [FieldName] [nvarchar](50) NULL,
    [FieldType] [nvarchar](50) NULL,
 CONSTRAINT [PK_FormField] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)
) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[FormTemplate]    Script Date: 3/2/2020 10:10:22 PM ******/

/****** Object:  Table [dbo].[FormValue]    Script Date: 3/2/2020 10:10:22 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[FormValue](
    [FormId] [int] NOT NULL,
    [FieldId] [int] NOT NULL,
    [RowIndex] [int] NOT NULL,
    [FormValue] [nvarchar](50) NULL,
 CONSTRAINT [PK_FormValue] PRIMARY KEY CLUSTERED 
(
    [FormId] ASC,
    [FieldId] ASC,
    [RowIndex] ASC
)
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[FormField] ON 
GO
INSERT [dbo].[FormField] ([Id], [FormId], [FieldName], [FieldType]) VALUES (1, 1, N'FirstName', N'string')
GO
INSERT [dbo].[FormField] ([Id], [FormId], [FieldName], [FieldType]) VALUES (2, 1, N'LastName', N'string')
GO
INSERT [dbo].[FormField] ([Id], [FormId], [FieldName], [FieldType]) VALUES (3, 1, N'Place', N'string')
GO
INSERT [dbo].[FormField] ([Id], [FormId], [FieldName], [FieldType]) VALUES (4, 1, N'age', N'int')
GO
INSERT [dbo].[FormField] ([Id], [FormId], [FieldName], [FieldType]) VALUES (5, 1, N'dob', N'date')
GO
SET IDENTITY_INSERT [dbo].[FormField] OFF
GO
SET IDENTITY_INSERT [dbo].[FormTemplate] ON 
GO
INSERT [dbo].[FormTemplate] ([Id], [Name]) VALUES (1, N'Sample')
GO
SET IDENTITY_INSERT [dbo].[FormTemplate] OFF
GO
INSERT [dbo].[FormValue] ([FormId], [FieldId], [RowIndex], [FormValue]) VALUES (1, 1, 1, N'fname1')
GO
INSERT [dbo].[FormValue] ([FormId], [FieldId], [RowIndex], [FormValue]) VALUES (1, 2, 1, N'lname1')
GO
INSERT [dbo].[FormValue] ([FormId], [FieldId], [RowIndex], [FormValue]) VALUES (1, 2, 3, N'lname3')
GO
INSERT [dbo].[FormValue] ([FormId], [FieldId], [RowIndex], [FormValue]) VALUES (1, 4, 5, N'20')
GO
INSERT [dbo].[FormValue] ([FormId], [FieldId], [RowIndex], [FormValue]) VALUES (1, 5, 3, N'10/10/2020')
GO

1 Ответ

1 голос
/ 02 марта 2020

Это отвечает на оригинальную версию вопроса - а затем и на некоторые. Но я не обновляю ответы, чтобы соответствовать возникающим вопросам.

Похоже, вам нужны перекрестные объединения на трех «столах». Третий должен генерировать значения rowindex:

select f.id as formtemplateid, ff.id as formfieldid, v.rowindex,
       fv.value
from formtemplate f cross join
     formfield ff cross join
     (values (1), (2), (3), (4), (5)) v(rowindex) left join
     formvalues fv
     on fv.formtemplateid = f.id and
        fv.formfieldid = ff.id and
        fv.rowindex = v.rowindex
order by f.id, ff.id, v.rowindex;

РЕДАКТИРОВАТЬ:

Вы можете создать до 100 чисел с помощью рекурсивного CTE, выполнив:

with n as (
      select 1 as n
      union all
      select n + 1
      from n
      where n < 10  -- "10" is however many you want
     )
select n.n
from n;
...