Benutzer mit den meisten Antworten
Datensatz splitten

Frage
-
Hallo,
ich möchte gerne einen Datensatz in einzelne Teilen Splitten.
Um das Problem genauer zu beschreiben. Es gibt einen Auftrag mit der Stückzahl n für jedes Teil soll nun eine Prüfung statt finden. Also möchte ich eine Tabelle mit n Zeilen um für jedes Teil Prüfung ok oder eben nicht ok eingetragen werden kann. Wie kann ich es über SQL lösen das solch eine Tabelle erstellt wird.
Antworten
-
Hallo Freerider,
Du willst/must also basierend auf der Artikelnummer und der Stückzahl die Prüfungen persistent hinterlegen. Leider geht das nicht "in einem Schritt", da CTE (Common Table Expressions) nicht in einem CROSS APPLY verwendet warden können :(
Aber mit der folgenden Lösung (basierend auf Deinem Code) sollte das gehen:
-- Erstellen einer Inlinefunktion für die Rückgabe von -- n Datensätzen basierend auf einer Intervall-Variablen CREATE FUNCTION dbo.PruefAuftragListe (@Id INT, @Intervall INT) RETURNS TABLE AS RETURN ( WITH c AS ( SELECT 1 AS RN, artnr FROM dbo.gssauftrag WHERE id = @Id UNION ALL SELECT RN + 1 AS RN, artnr FROM c WHERE RN <= @Intervall - 1 ) SELECT * FROM c ); GO
Die obige Funktion ist eine Inlinefunktion. Sie liefert mit Hilfe einer rekursiven Abfrage auf gssauftrag die Anzahl von Datensätzen für jede übergebene ID!
Diese Funktion mußt Du nur noch in einem SELECT-Statement verwenden, dass die Daten persistent in Deine Hilfstabelle postet!
SELECT PAL.RN, PAL.artnr FROM dbo.gssauftrag AS G CROSS APPLY dbo.PruefAuftragListe(G.Id, G.stkz) AS PAL GO
Das obige Beispiel zeigt nur den SELECT-Aufruf. Aber er zeigt das generelle Verständnis für die Anwendung der zuvor erstellen Funktion. Mit Hilfe des SELECT-Statements solltest Du bereits erkennen, wie die Ausgabe zu verwenden ist.
Ich vermute, dass sich in Deinem Design ein Fehler eingeschlichen hat, da Du eine [Auftrags_Id] einfügen möchtest. Im Result zeigst Du aber die Art_Nr. Da ich hier nicht sicher bin, was Du tatsächlich willst, kannst/must Du die Funktion entsprechend umgestalten.
Weitere Literatur zu den behandelten Themen findest Du hier:
recursive CTE: https://technet.microsoft.com/de-de/library/ms186243
CROSS APPLY: https://technet.microsoft.com/de-de/library/ms175156.aspx
MCM - SQL Server 2008
MCSE - SQL Server 2012
db Berater GmbH
SQL Server Blog (german only)- Als Antwort vorgeschlagen Christoph Muthmann Freitag, 19. Februar 2016 07:24
- Als Antwort markiert Aleksander Chalabashiev Mittwoch, 2. März 2016 11:17
-
Ich habe das mal etwas umgestellt, da die DDL-Statements nicht ganz stimmig waren. Außerdem benutze ich jetzt temporäre Tabellen zum testen.
Das Ergebnis ist erst mal NULL.
CREATE TABLE [#gssauftrag]( [id] [int] IDENTITY(1,1) NOT NULL, [artnr] [varchar](50) NOT NULL, [stkz] [int] NOT NULL, CONSTRAINT [PK_GSS_1] PRIMARY KEY CLUSTERED ( [id] ASC ) ); gO insert into #gssauftrag(artnr,stkz) values ('1234','30'),('2345','20'),('3456','10'); CREATE TABLE #ergebnis( [id] [int] identity NOT NULL, [ergebnis] [varchar](15) NOT NULL, CONSTRAINT [PK_ergebnis] PRIMARY KEY NONCLUSTERED ( [id] ASC ) ); GO insert into #ergebnis (ergebnis) values ('ok'),('nacharbeit'),('ausschuss'),('pruefausnahme'); CREATE TABLE #pruefauftrag( [id] [int] IDENTITY NOT NULL, [auftrags_id] [int] NOT NULL, [ergebnis_id] [int] NULL, CONSTRAINT [PK_pruefauftrag] PRIMARY KEY CLUSTERED ( [id] ASC ) ); GO With Nummern as (Select 1 as ID UNION ALL Select ID + 1 as ID from Nummern Where ID < 100) insert into #pruefauftrag(auftrags_id, ergebnis_id) Select g.artnr, NULL as ergebnis_ID from #gssauftrag g, Nummern n where n.ID <= g.stkz order by g.artnr, n.ID ; Select id, auftrags_id, ergebnis_id from #pruefauftrag order by id; go drop table #gssauftrag; drop table #ergebnis; drop table #pruefauftrag;
Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu
- Als Antwort vorgeschlagen Christoph Muthmann Freitag, 19. Februar 2016 07:25
- Als Antwort markiert Aleksander Chalabashiev Mittwoch, 2. März 2016 11:16
Alle Antworten
-
Die Quelldaten bestehen aus einer Tabelle mit den Spalten Auftrags_id, Artikelnummer und Stückzahl und das Ergebnis soll eine Tabelle pro Auftrags_id sein in der es eine Spalte Pruef_id, Auftrags_id und Ergebnis_id gibt diese Tabelle sollte dann der Stückzahl entsprechend viele Zeilen haben und wird über php und html im Browser dargestellt so dass der Prüfer die Möglichkeit hat per dropdown pro stück jeweils auszuwählen ob das Teil ok ist oder ob es einen Fehler hat
-
Hi,
poste bitte die Tabelle(n) als CREATE TABLE Statement, einige Beispieldaten als INSERT INTO Statement und dazu dann bitte das gewünschte Ergebnis.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
CREATE TABLE [dbo].[gssauftrag]([id] [int] IDENTITY(1,1) NOT NULL,[artnr] [varchar](50) NOT NULL,[stkz] [int] NOT NULL,CONSTRAINT [PK_GSS_1] PRIMARY KEY CLUSTERED([id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GOinsert into fes.dbo.gssauftrag(artnr,stkz)values ('1234','30'),('2345','20'),('3456','10');CREATE TABLE [dbo].[ergebnis]([id] [int] NOT NULL,[ergebnis] [varchar](15) NOT NULL,CONSTRAINT [PK_ergebnis] PRIMARY KEY NONCLUSTERED([id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GOinsert into fes.dbo.ergebnis (ergebnis)values ('ok','nacharbeit','ausschuss','pruefausnahme');CREATE TABLE [dbo].[pruefauftrag]([id] [int] NOT NULL,[auftrags_id] [int] NOT NULL,[ergebnis_id] [int] NOT NULL,CONSTRAINT [PK_pruefauftrag] PRIMARY KEY CLUSTERED([id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GOALTER TABLE [dbo].[pruefauftrag] WITH CHECK ADD CONSTRAINT [FK_pruefauftrag_gssauftrag] FOREIGN KEY([auftrags_id])REFERENCES [dbo].[gssauftrag] ([id])GOALTER TABLE [dbo].[pruefauftrag] CHECK CONSTRAINT [FK_pruefauftrag_gssauftrag]GOErgebnis soll dann eine Tabelle dieser art sein
pruef_id auftrags_id ergebnis_id 1 1234 2 1234 3 1234 4 1234 5 1234 6 1234 7 1234 8 1234 9 1234 10 1234 11 1234 12 1234 13 1234 14 1234 15 1234 16 1234 17 1234 18 1234 19 1234 20 1234 21 1234 22 1234 23 1234 24 1234 25 1234 26 1234 27 1234 28 1234 29 1234
30 1234
-
Das Ergebnis soll dann mit mit jedem weiteren Auftrag so ausshen
pruef_id auftrags_id ergebnis_id 1 1234 2 1234 3 1234 4 1234 5 1234 6 1234 7 1234 8 1234 9 1234 10 1234 11 1234 12 1234 13 1234 14 1234 15 1234 16 1234 17 1234 18 1234 19 1234 20 1234 21 1234 22 1234 23 1234 24 1234 25 1234 26 1234 27 1234 28 1234 29 1234 30 1234 31 2345 32 2345 33 2345 34 2345 35 2345 36 2345 37 2345 38 2345 39 2345 40 2345 41 2345 42 2345 43 2345 44 2345 45 2345 46 2345 47 2345 48 2345 49 2345 50 3456 51 3456 52 3456 53 3456 54 3456 55 3456 56 3456 57 3456 58 3456 59 3456 60 3456 -
Ich habe das mal etwas umgestellt, da die DDL-Statements nicht ganz stimmig waren. Außerdem benutze ich jetzt temporäre Tabellen zum testen.
Das Ergebnis ist erst mal NULL.
CREATE TABLE [#gssauftrag]( [id] [int] IDENTITY(1,1) NOT NULL, [artnr] [varchar](50) NOT NULL, [stkz] [int] NOT NULL, CONSTRAINT [PK_GSS_1] PRIMARY KEY CLUSTERED ( [id] ASC ) ); gO insert into #gssauftrag(artnr,stkz) values ('1234','30'),('2345','20'),('3456','10'); CREATE TABLE #ergebnis( [id] [int] identity NOT NULL, [ergebnis] [varchar](15) NOT NULL, CONSTRAINT [PK_ergebnis] PRIMARY KEY NONCLUSTERED ( [id] ASC ) ); GO insert into #ergebnis (ergebnis) values ('ok'),('nacharbeit'),('ausschuss'),('pruefausnahme'); CREATE TABLE #pruefauftrag( [id] [int] IDENTITY NOT NULL, [auftrags_id] [int] NOT NULL, [ergebnis_id] [int] NULL, CONSTRAINT [PK_pruefauftrag] PRIMARY KEY CLUSTERED ( [id] ASC ) ); GO With Nummern as (Select 1 as ID UNION ALL Select ID + 1 as ID from Nummern Where ID < 100) insert into #pruefauftrag(auftrags_id, ergebnis_id) Select g.artnr, NULL as ergebnis_ID from #gssauftrag g, Nummern n where n.ID <= g.stkz order by g.artnr, n.ID ; Select id, auftrags_id, ergebnis_id from #pruefauftrag order by id; go drop table #gssauftrag; drop table #ergebnis; drop table #pruefauftrag;
Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu
- Als Antwort vorgeschlagen Christoph Muthmann Freitag, 19. Februar 2016 07:25
- Als Antwort markiert Aleksander Chalabashiev Mittwoch, 2. März 2016 11:16
-
Hallo Freerider,
Du willst/must also basierend auf der Artikelnummer und der Stückzahl die Prüfungen persistent hinterlegen. Leider geht das nicht "in einem Schritt", da CTE (Common Table Expressions) nicht in einem CROSS APPLY verwendet warden können :(
Aber mit der folgenden Lösung (basierend auf Deinem Code) sollte das gehen:
-- Erstellen einer Inlinefunktion für die Rückgabe von -- n Datensätzen basierend auf einer Intervall-Variablen CREATE FUNCTION dbo.PruefAuftragListe (@Id INT, @Intervall INT) RETURNS TABLE AS RETURN ( WITH c AS ( SELECT 1 AS RN, artnr FROM dbo.gssauftrag WHERE id = @Id UNION ALL SELECT RN + 1 AS RN, artnr FROM c WHERE RN <= @Intervall - 1 ) SELECT * FROM c ); GO
Die obige Funktion ist eine Inlinefunktion. Sie liefert mit Hilfe einer rekursiven Abfrage auf gssauftrag die Anzahl von Datensätzen für jede übergebene ID!
Diese Funktion mußt Du nur noch in einem SELECT-Statement verwenden, dass die Daten persistent in Deine Hilfstabelle postet!
SELECT PAL.RN, PAL.artnr FROM dbo.gssauftrag AS G CROSS APPLY dbo.PruefAuftragListe(G.Id, G.stkz) AS PAL GO
Das obige Beispiel zeigt nur den SELECT-Aufruf. Aber er zeigt das generelle Verständnis für die Anwendung der zuvor erstellen Funktion. Mit Hilfe des SELECT-Statements solltest Du bereits erkennen, wie die Ausgabe zu verwenden ist.
Ich vermute, dass sich in Deinem Design ein Fehler eingeschlichen hat, da Du eine [Auftrags_Id] einfügen möchtest. Im Result zeigst Du aber die Art_Nr. Da ich hier nicht sicher bin, was Du tatsächlich willst, kannst/must Du die Funktion entsprechend umgestalten.
Weitere Literatur zu den behandelten Themen findest Du hier:
recursive CTE: https://technet.microsoft.com/de-de/library/ms186243
CROSS APPLY: https://technet.microsoft.com/de-de/library/ms175156.aspx
MCM - SQL Server 2008
MCSE - SQL Server 2012
db Berater GmbH
SQL Server Blog (german only)- Als Antwort vorgeschlagen Christoph Muthmann Freitag, 19. Februar 2016 07:24
- Als Antwort markiert Aleksander Chalabashiev Mittwoch, 2. März 2016 11:17
-
Die Ausgangstabelle enthält eigentlich noch mehr Spalten jedoch ist durch die Auftrags_id und die Stückzahl eigentlich alles notwendige an Informationen abgedeckt um die Möglichkeit zu haben für jedes Teil die durchgeführte Prüfung zu dokumentieren. Denke ich zumindest, ich kann aber auch falsch liegen. Ich teste die Lösung mit der Inline Funktion einfach auch noch und schaue was sich am besten einbinden lässt.
Danke für die echt super Hilfe. Einen schönen Tag noch
-
Ich habe nochmal eine Frage bezüglich dieser Abfrage.
-- Erstellen einer Inlinefunktion für die Rückgabe von -- n Datensätzen basierend auf einer Intervall-Variablen CREATE FUNCTION dbo.PruefAuftragListe (@Id INT, @Intervall INT) RETURNS TABLE AS RETURN ( WITH c AS ( SELECT 1 AS RN, artnr FROM dbo.gssauftrag WHERE id = @Id UNION ALL SELECT RN + 1 AS RN, artnr FROM c WHERE RN <= @Intervall - 1 ) SELECT * FROM c ); GO
Wie muss ich die Abfrage ändern um lediglich für eine bestimmte Artikelnummer die Tabelle für die einzelnen Prüfungen zu erhalten.
-
Hallo!
1.) Solltest Du nicht in einem beantworteten Thread neue Fragen stellen. Das reduziert die Wahrscheinlichkeit auf eine Antwort deutlich.
2.) Wirst Du wahrscheinlich beim Anker-Element die Where-Bedingung erweiterung müssen. Also in der Art:
WHERE id = @Id and ID in (11223344, 55667788)
Damit werden nur noch für die beiden Artikelnummern die Listen erzeugt.
Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu