Benutzer mit den meisten Antworten
If then else in where Klausel

Frage
-
Hallo zusammen,
ich hoffe ihr könnt mir weiterhelfen.Folgende Abfrage habe ich gerade:
select top 1 tww.[Value] from [Toleranzwerte] tww inner join [Toleranzklassen] twk on tww.[Parameter_ID] = twk.[Parameter_ID] inner join [Toleranzbereiche] twb on tww.[Row_ID] = twb.[Row_ID] where tww.[Normreihe_ID] = (select top 1 twt.normreihe_id from [ToleranceTables] as twt where twt.betreff = 'Griffe') and convert(int, twb.[Normreihe_ID]) = convert(int, (select top 1 twt.normreihe_id from [ToleranceTables] as twt where twt.betreff = 'Griffe')) and tww.[Value] is not null and tww.[Parameter_ID] = twk.[Parameter_id] --and twk.Name COLLATE Latin1_General_CS_AS = 'a9' COLLATE Latin1_General_CS_AS --and convert(int, substring(twb.[Interval], 2, charindex('&',twb.[Interval]) - 2)) < '50' --and convert(int, substring(twb.[Interval], charindex('&',twb.[Interval]) + 3, LEN(twb.Interval) - charindex('&',[Interval]) + 3)) >= '50' --and len(twb.[Interval]) > 5 and twk.Name COLLATE Latin1_General_CS_AS = 'Abstand_x' COLLATE Latin1_General_CS_AS and twb.Interval = '10001'
Mein der zeitiges Problem ist folgendes:
Die derzeitige Abfrage funktioniert im Moment nur mit den letzten beiden Zeilen.
Tausche ich den Begriff "Griffe" gegen "ISO Passungen" aus, so funktioniert dieser nur mit den 4 auskommentierten Zeilen.
Der Unterschied ist das bei "Griffe" im twb.Interval eine 5 Stellige Zahl vorhanden ist (10001)
und bei "ISO Passungen ist der twb.Interval (>0&<=50) deswegen zerlege ich den Bereich mit SUBSTRING.Habe ich alle Zeilen im Skript aktiviert und in der vorletzten Zeile das "and" gegen ein "or" getauscht (das sollte ja eigentlich funktionieren) bekomme ich immer folgende Meldung --> Ein ungültiger Längenparameter wurde an die LEFT- oder SUBSTRING-Funktion übergeben. <--
Mit der jeweils richtigen Angabe und den richtigen Zeilen funktioniert das Skript einwandfrei.Ich möchte nun am liebsten das sobald im twb.Interval ein "&" Zeichen ist die 4 auskommentierten Zeilen benutzt werden, ansonsten die beiden letzten Zeilen.
Mit der CASE Anweisung habe ich schon ein wenig rum gespielt, aber das klappt alles nicht so wie ich mir vorstelle.
Ich bin nun auch an einem Punkt an dem ich nicht mehr weiterkomme =( und den Wald vor Bäumen nicht mehr sehe.Danke und Gruß
StephanP.S.: Im Moment arbeite ich mit dem Management Studio 2014 und SQL 2012 Express
Derzeit nutze ich das Management Studio 2014 mit SQL 2012 Express.
Derzeit nutze ich das Management Studio 2014 mit SQL 2012 Express.
Antworten
-
Hallo Stephan, ich habe dir folgende Lösung vorzuschlagen. Du kannst die Parameter wahlweise am Anfang auskommentieren. Beachte auch den Hinweis zu ntext:
/* https://msdn.microsoft.com/de-de/library/ms187993%28v=sql.120%29.aspx?f=255&MSPPError=-2147217396 Die Datentypen ntext, text und image werden in einer zukünftigen Version von Microsoft SQL Server entfernt. Vermeiden Sie diese Datentypen bei Neuentwicklungen, und planen Sie die Änderung derjenigen Anwendungen, in denen diese Datentypen derzeit verwendet werden. Verwenden Sie stattdessen nvarchar(max), varchar(max) und varbinary(max). */ Declare @Wert int = 10001, @Betreff nvarchar(50) = N'Griffe', @Name nvarchar(50) = N'Abstand_x'; /* Set @Wert = 45; Set @Betreff = N'ISO Passungen'; Set @Name = N'a9'; */ With Vorselektion as ( SELECT [Row_ID] ,[Normreihe_ID] ,[Interval], CHARINDEX('>', Interval) c1, CHARINDEX('&', Interval) c2 FROM [dbo].[Toleranzbereiche] ), Intervalle as (Select Row_ID, Normreihe_ID, Interval, case when c2 <> 0 then SUBSTRING(Interval, c1+1, c2-(c1+1)) else Interval end as Bereich1, case when c2 <> 0 then SUBSTRING(Interval, c2+3, LEN(Interval) - c2) else Interval end as Bereich2 from Vorselektion ) select top 1 tww.[Value] from [Toleranzwerte] tww inner join [Toleranzklassen] twk on tww.[Parameter_ID] = twk.[Parameter_ID] inner join Intervalle twb on tww.[Row_ID] = twb.[Row_ID] and twb.Normreihe_ID = tww.Normreihe_ID where tww.[Normreihe_ID] = (select top 1 twt.normreihe_id from [ToleranceTables] as twt where twt.betreff = @Betreff) and tww.[Value] is not null and twk.Name COLLATE Latin1_General_CS_AS = @Name COLLATE Latin1_General_CS_AS and (@Wert > twb.Bereich1 and @Wert <=twb.Bereich2) or (twb.Bereich1 = twb.Bereich2 and @Wert = twb.Bereich1);
Einen schönen Tag noch,
Christoph
--
Data Platform MVP - http://www.insidesql.org/blogs/cmu- Als Antwort markiert Stephan Mensing Mittwoch, 2. Dezember 2015 10:01
Alle Antworten
-
Hallo Stephan,
poste doch bitte die CREATE TABLE Statements für beide Tabellen, dazu ein paar INSERT INTO Statements für die Beispieldaten und dann noch das gewünschte Ergebnis als Tabelle oder Screenshot. Das hilft uns bei der Problemlösung und sorgt dafür, dass wir dir schneller und effizienter helfen können.
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
- Bearbeitet Stefan FalzModerator Dienstag, 1. Dezember 2015 16:53
-
Hallo Stefan,
daran hätte ich auch selber denken können *schäm*
und hier die angeforderten Daten.Einmal die Tabellen und ein paar Beispiel Werte.
Bei "ISO Passungen" und "a9" kommt als Ergebnis "-382|-320"
Bei "Griffe" und "10001" kommt als Ergebnis "-60"Danke und Gruß
StephanCREATE TABLE [dbo].[ToleranceTables]( [Normreihe_ID] [int] NULL, [Betreff] [nvarchar](50) NULL, [Tab_Timestamp] [nvarchar](50) NULL ) ON [PRIMARY] CREATE TABLE [dbo].[Toleranzbereiche]( [Row_ID] [int] NULL, [Normreihe_ID] [int] NULL, [Interval] [nvarchar](50) NULL ) ON [PRIMARY] CREATE TABLE [dbo].[Toleranzklassen]( [Parameter_ID] [int] NULL, [Normreihe_ID] [int] NULL, [ParameterType_ID] [int] NULL, [Name] [nvarchar](50) NULL, [Sort] [int] NULL, [Measure_ID] [int] NULL, [Timestamp] [nvarchar](50) NULL, [IsEdgeBar] [int] NULL ) ON [PRIMARY] CREATE TABLE [dbo].[Toleranzwerte]( [Value_ID] [int] NULL, [Normreihe_ID] [int] NULL, [Parameter_ID] [int] NULL, [Row_ID] [int] NULL, [Value] [ntext] NULL ) ON [PRIMARY] INSERT [dbo].[ToleranceTables] ([Normreihe_ID], [Betreff], [Tab_Timestamp]) VALUES (4, N'ISO Passungen', N'2013 4 26 11 41 57') INSERT [dbo].[ToleranceTables] ([Normreihe_ID], [Betreff], [Tab_Timestamp]) VALUES (3, N'Griffe', NULL) INSERT [dbo].[Toleranzbereiche] ([Row_ID], [Normreihe_ID], [Interval]) VALUES (82, 4, N'>30&<=40') INSERT [dbo].[Toleranzbereiche] ([Row_ID], [Normreihe_ID], [Interval]) VALUES (84, 4, N'>40&<=50') INSERT [dbo].[Toleranzbereiche] ([Row_ID], [Normreihe_ID], [Interval]) VALUES (86, 4, N'>50&<=65') INSERT [dbo].[Toleranzbereiche] ([Row_ID], [Normreihe_ID], [Interval]) VALUES (88, 4, N'>65&<=80') INSERT [dbo].[Toleranzbereiche] ([Row_ID], [Normreihe_ID], [Interval]) VALUES (3, 3, N'10001') INSERT [dbo].[Toleranzbereiche] ([Row_ID], [Normreihe_ID], [Interval]) VALUES (5, 3, N'10002') INSERT [dbo].[Toleranzklassen] ([Parameter_ID], [Normreihe_ID], [ParameterType_ID], [Name], [Sort], [Measure_ID], [Timestamp], [IsEdgeBar]) VALUES (76, 4, 10, N'A9', 1, 0, N'2006 10 25 23 14 9', 1) INSERT [dbo].[Toleranzklassen] ([Parameter_ID], [Normreihe_ID], [ParameterType_ID], [Name], [Sort], [Measure_ID], [Timestamp], [IsEdgeBar]) VALUES (96, 4, 10, N'a9', 6, 0, N'2006 10 25 23 14 19', 1) INSERT [dbo].[Toleranzklassen] ([Parameter_ID], [Normreihe_ID], [ParameterType_ID], [Name], [Sort], [Measure_ID], [Timestamp], [IsEdgeBar]) VALUES (3, 3, 10, N'Abstand_x', 1, 0, N'2015 11 16 15 53 00', 1) INSERT [dbo].[Toleranzklassen] ([Parameter_ID], [Normreihe_ID], [ParameterType_ID], [Name], [Sort], [Measure_ID], [Timestamp], [IsEdgeBar]) VALUES (5, 3, 10, N'Abstand_Bohrungen', 2, 0, N'2015 11 16 15 53 00', 1) INSERT [dbo].[Toleranzklassen] ([Parameter_ID], [Normreihe_ID], [ParameterType_ID], [Name], [Sort], [Measure_ID], [Timestamp], [IsEdgeBar]) VALUES (7, 3, 10, N'H', 3, 0, N'2015 11 16 15 53 00', 1) INSERT [dbo].[Toleranzklassen] ([Parameter_ID], [Normreihe_ID], [ParameterType_ID], [Name], [Sort], [Measure_ID], [Timestamp], [IsEdgeBar]) VALUES (9, 3, 10, N'D', 4, 0, N'2015 11 16 17 24 50', 1) INSERT [dbo].[Toleranzwerte] ([Value_ID], [Normreihe_ID], [Parameter_ID], [Row_ID], [Value]) VALUES (700, 4, 76, 84, N'+320|382') INSERT [dbo].[Toleranzwerte] ([Value_ID], [Normreihe_ID], [Parameter_ID], [Row_ID], [Value]) VALUES (990, 4, 96, 84, N'-382|-320') INSERT [dbo].[Toleranzwerte] ([Value_ID], [Normreihe_ID], [Parameter_ID], [Row_ID], [Value]) VALUES (9, 3, 3, 3, N'-60') INSERT [dbo].[Toleranzwerte] ([Value_ID], [Normreihe_ID], [Parameter_ID], [Row_ID], [Value]) VALUES (11, 3, 3, 5, N'-50') INSERT [dbo].[Toleranzwerte] ([Value_ID], [Normreihe_ID], [Parameter_ID], [Row_ID], [Value]) VALUES (13, 3, 3, 7, N'-55')
-
Hallo Stephan, ich habe dir folgende Lösung vorzuschlagen. Du kannst die Parameter wahlweise am Anfang auskommentieren. Beachte auch den Hinweis zu ntext:
/* https://msdn.microsoft.com/de-de/library/ms187993%28v=sql.120%29.aspx?f=255&MSPPError=-2147217396 Die Datentypen ntext, text und image werden in einer zukünftigen Version von Microsoft SQL Server entfernt. Vermeiden Sie diese Datentypen bei Neuentwicklungen, und planen Sie die Änderung derjenigen Anwendungen, in denen diese Datentypen derzeit verwendet werden. Verwenden Sie stattdessen nvarchar(max), varchar(max) und varbinary(max). */ Declare @Wert int = 10001, @Betreff nvarchar(50) = N'Griffe', @Name nvarchar(50) = N'Abstand_x'; /* Set @Wert = 45; Set @Betreff = N'ISO Passungen'; Set @Name = N'a9'; */ With Vorselektion as ( SELECT [Row_ID] ,[Normreihe_ID] ,[Interval], CHARINDEX('>', Interval) c1, CHARINDEX('&', Interval) c2 FROM [dbo].[Toleranzbereiche] ), Intervalle as (Select Row_ID, Normreihe_ID, Interval, case when c2 <> 0 then SUBSTRING(Interval, c1+1, c2-(c1+1)) else Interval end as Bereich1, case when c2 <> 0 then SUBSTRING(Interval, c2+3, LEN(Interval) - c2) else Interval end as Bereich2 from Vorselektion ) select top 1 tww.[Value] from [Toleranzwerte] tww inner join [Toleranzklassen] twk on tww.[Parameter_ID] = twk.[Parameter_ID] inner join Intervalle twb on tww.[Row_ID] = twb.[Row_ID] and twb.Normreihe_ID = tww.Normreihe_ID where tww.[Normreihe_ID] = (select top 1 twt.normreihe_id from [ToleranceTables] as twt where twt.betreff = @Betreff) and tww.[Value] is not null and twk.Name COLLATE Latin1_General_CS_AS = @Name COLLATE Latin1_General_CS_AS and (@Wert > twb.Bereich1 and @Wert <=twb.Bereich2) or (twb.Bereich1 = twb.Bereich2 and @Wert = twb.Bereich1);
Einen schönen Tag noch,
Christoph
--
Data Platform MVP - http://www.insidesql.org/blogs/cmu- Als Antwort markiert Stephan Mensing Mittwoch, 2. Dezember 2015 10:01
-
Hallo Christoph,
das ist die Lösung die ich gesucht habe. An dieser Stelle ziehe ich meinen Hut oder besser gesagt meine Mütze =).Eine kleine Änderung musste ich nur noch vornehmen, aus "@Wert int = 10001" habe ich "@Wert nvarchar(50) = '10001'" gemacht.
Da ich ansonsten auf der Originalen DB eine Fehlermeldung bekomme.
-->Fehler beim Konvertieren des nvarchar-Werts '1,2' in den int-Datentyp.<--
Aus welche Grund auch immer er nicht in der Lage ist "1,2" in Integer umzuwandeln *seufz*
Das hatte mich aber schon mal ganz am Anfang geärgert und wurde von mir verdrängt.Zu diesem Teil:
-->
Die Datentypen ntext, text und image werden in einer zukünftigen Version von Microsoft SQL Server entfernt.
<--Da hatte ich unseren Entwickler schon mal drauf hingewiesen und er hat versprochen das bis 2017 bereinigt zu haben. Ich persönlich lasse mich überraschen ^^ aber die Originale DB stammt noch irgendwo aus Access und wurde mal umgebastelt auf SQL mit SQL 2005 oder so und ganz am Anfang war es mal eine Excel Tabelle.
Danke und Gruß
Stephan