none
If then else in where Klausel RRS feed

  • 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ß
       Stephan

    P.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.
    Dienstag, 1. Dezember 2015 14:24

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

    Mittwoch, 2. Dezember 2015 08:50
    Beantworter

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



    Dienstag, 1. Dezember 2015 16:52
    Moderator
  • 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ß
       Stephan

    CREATE 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')

    Mittwoch, 2. Dezember 2015 07:22
  • 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

    Mittwoch, 2. Dezember 2015 08:50
    Beantworter
  • 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

    Mittwoch, 2. Dezember 2015 10:00