Not using Where statement in a context - sql

Goal:
If you have the input data that is -10 then you should not use the WHERE statement in function.
Problem:
I do not know how to solve it in this context. You have to use WHERE and not WHERE depending on what input data you retrieve
Info:
If you use -10 as a input data then you should retrieve all data based on [dbo].[testing] and it is okay to retrieve data that is null in [dbo].[testing2] in relation to LEFT JOIN.
*The code and its data is a sample from production phase.
Thank you!
CREATE TABLE [dbo].[testing](
[id] [int] NULL,
[value] [varchar](30) NULL,
[category] [int] NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[testing2](
[id] [int] NULL,
[value] [varchar](30) NULL,
[category] [int] NULL,
[test_id] [int] NULL,
[id_type] [int] NOT NULL
) ON [PRIMARY]
CREATE FUNCTION dbo.testt (
#data int
)
RETURNS TABLE
AS
RETURN
(
SELECT
a.[id],
a.[value],
a.[category],
b.[id_type]
FROM [dbo].[testing] a left join [dbo].[testing2] b on a.id = b.[id]
where b.[id_type] = #data
)
INSERT INTO [test].[dbo].[testing] VALUES
(1, '', 2), (2, '', 3), (3, 'a', 2), (4, 'a', 2),
(5, 'b', 2), (6, 'b', 2), (7, 'c', 2), (8, 'c', 2),
(9, 'c', 2), (10, 'c', 2);
INSERT INTO [test].[dbo].[testing2] VALUES
(3, 'a' ,2 ,11 ,1), (4, 'a' ,2 ,11 ,1),
(5, 'a' ,2 ,11 ,0), (6, 'a' ,2 ,11 ,2);
select
s.[id],
s.[value],
s.[category],
s.[id_type]
from dbo.testt(1) s

Have your WHERE clause check if #data is either -10 or matches b.[id_type].
WHERE (#data = -10) OR (b.[id_type] = #data)

What about where b.[id_type] = #data OR #data = -10 in the testt function ?
So your function would be:
CREATE FUNCTION dbo.testt (
#data int
)
RETURNS TABLE
AS
RETURN
(
SELECT
a.[id],
a.[value],
a.[category],
b.[id_type]
FROM [dbo].[testing] a
LEFT JOIN [dbo].[testing2] b on a.id = b.[id]
WHERE b.[id_type] = #data OR #data = -10
)

Related

Self join to get the first classID for a report

I have the following table :
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[myTable]
(
[importID] [INT] IDENTITY(1,1) NOT NULL,
[classID] [INT] NOT NULL,
[priorReportID] [INT] NOT NULL,
[currentReportID] [INT] NOT NULL,
[dateStamp] AS (GETDATE())
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[myTable] ON
GO
INSERT INTO [dbo].[myTable] ([importID], [classID], [priorReportID], [currentReportID])
VALUES (1, 2069, 3825, 3833), (2, 2069, 3826, 3834),
(3, 2069, 3827, 3835), (4, 2069, 3832, 3836),
(5, 2091, 3889, 3890), (6, 2095, 3894, 3895),
(7, 2098, 3895, 3898), (8, 2098, 3896, 3899),
(9, 2098, 3897, 3900), (10, 2097, 2190, 2193),
(11, 2096, 2188, 2190), (12, 2094, 2187, 2188),
(13, 2093, 2180, 2187)
GO
SET IDENTITY_INSERT [dbo].[myTable] OFF
GO
I am trying to get the first ClassID when a particular report was created.
select *
from mytable
select *
from mytable
where currentReportID = 3833
select *
from mytable
where currentReportID = 3825
select *
from mytable
where currentReportID = 2193
select *
from mytable
where currentReportID = 2190
select *
from mytable
where currentReportID = 2188
select *
from mytable
where currentReportID = 2187
select *
from mytable
where currentReportID = 2180
In the example above: reportID = 2193 was actually created in classID = 2093.
Similarly, reportID = 3833 was created in classID = 2069.
Basically, I need to traverse down the records until there is no more currentReportID = priorReportID condition is satisfied.
Thanks in advance.

SQL Server CTE statement Varbinary(MAX) Not Returning the RootID

I have a hierarchy table to store a binary tree. I'm using a recursive query to retrieve the tree level based on the IntroducerID as the "RootID". The value returned as what I expected, but after the AgentId number increment reached 116, this CTE query doesn't return the Level value in hierarchical form.
Like it cannot trace the RootID anymore.
This is what my table structure looks like;
CREATE TABLE [dbo].[TblHierarchy]
(
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[AgentID] [bigint] NULL,
[AgentName] [varchar](50) NULL,
[RootID] [bigint] NULL,
[IntroducerID] [bigint] NULL,
[Description] [varchar](50) NULL,
[HierarchyTree] [hierarchyid] NULL
) ON [PRIMARY]
Below is the sample data from the table;
INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree])
VALUES (1, 1, N'Toh', 0, NULL, N'', NULL)
INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree])
VALUES (2, 2, N'Man', 1, 0, N'Child of Toh', NULL)
INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree])
VALUES (3, 3, N'Rul', 1, 0, N'Child of Toh', NULL)
INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree])
VALUES (4, 4, N'Rafiq', 2, 2, N'Child of Man', NULL)
INSERT [dbo].[TblHierarchy] ([ID], [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree])
VALUES (5, 5, N'Paan', 2, 2, N'Child of Man', NULL)
And this is the query to retrieve the info.
WITH CTE AS
(
SELECT
H1.AgentID,
H1.RootID,
H1.AgentName,
H1.Description [Parent],
Description [Self Description],
CAST(AgentID AS varbinary(MAX)) [Level],
CAST (h1.AgentID AS varchar(max)) [LevelID],
CAST (H1.IntroducerID AS varchar(max)) [IntroducerID]
FROM
TblHierarchy H1
WHERE
H1.RootID = 3
UNION ALL
SELECT
H2.AgentID,
H2.RootID,
H2.AgentName,
c.[Self Description],
Description [Self Description],
c.[Level]+CAST(h2.AgentID AS varbinary(MAX)) AS [Level] ,
c.[LevelID] + '>' + CAST (h2.AgentID AS varchar(max)) [LevelID],
CAST (H2.IntroducerID AS varchar(max)) [IntroducerID]
FROM
TblHierarchy H2
INNER JOIN
CTE c ON h2.RootID = c.AgentID
)
SELECT *
FROM CTE
CROSS APPLY
(SELECT
SUBSTRING(LevelID, 1, CHARINDEX('>', LevelID + '>') - 1) ) c(RootLevelID)
ORDER BY
[Level] DESC
OPTION (MAXRECURSION 0)
I do not fully understand your needs (especially what you are trying to achieve with all this casting...), but check this out:
EDIT: After some thinking I hope I got it
I removed my previous suggestion, where I had to change your input data. The following uses your input data unchanged and links via AgentID and RootID.
CREATE TABLE [dbo].[TblHierarchy](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[AgentID] [bigint] NULL,
[AgentName] [varchar](50) NULL,
[RootID] [bigint] NULL,
[IntroducerID] [bigint] NULL,
[Description] [varchar](50) NULL,
[HierarchyTree] [hierarchyid] NULL
) ON [PRIMARY];
INSERT [dbo].[TblHierarchy] ( [AgentID], [AgentName], [RootID], [IntroducerID], [Description], [HierarchyTree])
VALUES
( 1, N'Toh', 0, NULL, N'', NULL)
,( 2, N'Man', 1, 0, N'Child of Toh', NULL)
,( 3, N'Rul', 1, 0, N'Child of Toh', NULL)
,( 4, N'Rafiq', 2, 2, N'Child of Man', NULL)
,( 5, N'Paan', 2, 2, N'Child of Man', NULL)
SELECT * FROM dbo.TblHierarchy;
WITH recCTE AS
(
SELECT h.ID
,h.AgentID
,h.AgentName
,h.RootID
,h.IntroducerID
,h.[Description]
,CAST(h.[Description] AS VARCHAR(MAX)) AS HierDescr
FROM dbo.TblHierarchy AS h WHERE h.IntroducerID IS NULL
UNION ALL
SELECT h.ID
,h.AgentID
,h.AgentName
,h.RootID
,h.IntroducerID
,h.[Description]
,r.HierDescr + '/' + h.[Description]
FROM recCTE AS r
INNER JOIN dbo.TblHierarchy AS h ON h.RootID=r.AgentID
)
SELECT * FROM recCTE
GO
DROP TABLE [dbo].[TblHierarchy];

Display the latest row only

Goal:
If you retrieve any duplicate data that is data in the column secondid, then you to retrieve one row only from the latest date. For instance in the data below I have two different datetime, I would like to retrieve the data '2016-05-02 07:34:14.377' from value 6 in column secondid.
Problem:
I code seems not to be working and what am I missing.
Info:
There are many data in and you cannot hard code the value in in the code.
CREATE TABLE [dbo].[testing2](
[id] [int] NOT NULL,
[secondid] [int] NULL,
[value] [varchar](30) NULL,
[category] [int] NULL,
[test_id] [int] NULL,
[id_type] [int] NOT NULL,
[Testing2Datetime] [datetime] not NULL,
CONSTRAINT [PK_testing2] 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]
INSERT INTO [test].[dbo].[testing2]
VALUES (3, 3, 'a' ,2 ,11 ,1, '2016-05-01 07:34:14.377');
INSERT INTO [test].[dbo].[testing2]
VALUES (4, 4, 'a' ,2 ,11 ,1, '2016-05-01 07:34:14.377');
INSERT INTO [test].[dbo].[testing2]
VALUES (5, 5, 'a' ,2 ,11 ,0, '2016-05-01 07:34:14.377');
INSERT INTO [test].[dbo].[testing2]
VALUES (6, 6, 'a' ,2 ,11 ,2, '2016-05-01 07:34:14.377');
INSERT INTO [test].[dbo].[testing2]
VALUES (7, 6, 'a' ,2 ,11 ,2, '2016-05-02 07:34:14.377');
select
bb.secondid,
max(bb.Testing2Datetime)
from [dbo].[testing2] bb
group by
bb.secondid,
bb.Testing2Datetime
The maximum value of Testing2Datetime per Testing2Datetime is the Testing2Datetime itself. You should remove it from the group by clause and retrieve the maximum value per secondid only:
select
bb.secondid,
max(bb.Testing2Datetime)
from [dbo].[testing2] bb
group by
bb.secondid -- Here!
Remove bb.Testing2Datetime column from Group by
select
bb.secondid,
max(bb.Testing2Datetime) as [Max_Testing2Datetime]
from [dbo].[testing2] bb
group by
bb.secondid
or even this(Row_Number window function)
select *
from
(
select
bb.secondid,
bb.Testing2Datetime,
Row_number()over(partition by bb.secondid order by bb.Testing2Datetime desc) as RN
from [dbo].[testing2] bb
) A
Where RN = 1

Why isn't STUFF and FOR XML PATH not concenating?

I have these two tables
CREATE TABLE [dbo].[Things](
[testid] [int] NOT NULL,
[testdesc] [varchar](10) NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[ThingsStaging](
[otherid] [int] NOT NULL,
[testid] [int] NOT NULL
) ON [PRIMARY]
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (1, N'Stuff')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (2, N'Things')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (3, N'Orcs')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (4, N'Grubs')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (5, N'Shrooms')
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (1, 1)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (1, 2)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (1, 3)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (2, 3)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (2, 4)
;with allThings(otherid, descs)
as
(
select ts.otherid ,
stuff ((select ', ' + blah.testdesc as [text()]
from (
select distinct t.testdesc
from Things as t
where t.testid = ts.testid ) as blah
for xml path('')), 1, 1, '') as stuffs
from ThingsStaging as ts
)
select *
from allThings
Now when run this query, I get
otherid stuffs
1 Stuff
1 Things
1 Orcs
2 Orcs
2 Grubs
But I should get:
otherid stuffs
1 Stuff, Things, Orcs
2 Orcs, Grubs
I'm not understanding what I'm doing wrong.
I understand what I did wrong. Code will explain better.
select otherid, stuff((select ', ' + t.testdesc as [text()]
from Things as t
inner join ThingsStaging as its on t.testid = its.testid
where its.otherid = ts.otherid
for xml path('')), 1, 1, '') as descs
from ThingsStaging as ts
group by otherid

SQL Query to Filter a Table using another Table

I currently have 2 SQL tables that look like this:
and...
I need to write a SELECT statement that retrieves all products from the DataTable that contain rows that match the FilterTable.
So based on my example tables above, if I were to run the query, it would return the following result:
I recently found a question that kind of attempts this:
SQL query where ALL records in a join match a condition?
but have been unsuccessful in implementing something similar
Note - I am using Microsoft SQL Server 2008
This is a little complicated, but here is one solution. Basically you need to check to see how many records from the datatable match all the records from the filtertable. This uses a subquery to do that:
SELECT *
FROM DataTable
WHERE ID IN (
SELECT DT.ID
FROM DataTable DT
JOIN FilterTable FT ON FT.Name = DT.Name
AND FT.Value = DT.VALUE
GROUP BY DT.ID
HAVING COUNT(*) = (SELECT COUNT(*) FROM FilterTable)
)
SQL Fiddle Demo
This will work:
SELECT * FROM Data WHERE ID NOT IN (
SELECT ID FROM Data JOIN Filter
on Data.Name = Filter.Name and Data.Value <> Filter.Value
)
I set up a SQL Fiddle if you want to try other things:
http://sqlfiddle.com/#!3/38b87/6
EDIT:
Better answer:
SELECT *
FROM DATA
WHERE ID NOT IN (
SELECT ID
FROM DATA
JOIN Filter ON DATA.Name = Filter.Name
AND DATA.Value <> Filter.Value
) AND ID IN
(
SELECT ID
FROM DATA
JOIN Filter ON DATA.Name = Filter.Name
)
This now fits where there is at least one filter that matches, and none that don't.
In case you can use sp_executesql (you are using procedure).
SET NOCOUNT ON
GO
CREATE TABLE Data
(
[ID] INT
,[Name] VARCHAR(12)
,[Value] VARCHAR(2)
)
CREATE TABLE Filter
(
[Name] VARCHAR(12)
,[Value] VARCHAR(2)
)
INSERT INTO Data ([ID], [Name], [Value])
VALUES (1, 'productname', 'A')
,(1, 'cost', '20')
,(1, 'active', 'Y')
,(2, 'productname', 'A')
,(2, 'cost', '20')
,(2, 'active', 'N')
,(3, 'productname', 'B')
,(3, 'cost', '20')
,(3, 'active', 'Y')
,(4, 'productname', 'A')
,(4, 'cost', '20')
,(4, 'active', 'Y')
INSERT INTO Filter ([Name], [Value])
VALUES ('productname', 'A')
,('active', 'Y')
DECLARE #SQLColumns NVARCHAR(MAX) = SUBSTRING((SELECT DISTINCT ',[' +[Name] +']' FROM Data FOR XML PATH('')),2,4000)
DECLARE #SQLFilterColumns NVARCHAR(MAX) = SUBSTRING((SELECT 'AND [' +[Name] +'] = ''' + [Value] + ''' ' FROM Filter FOR XML PATH('')),4,4000)
DECLARE #SQLStatement NVARCHAR(MAX) = N'
;WITH DataSource ([ID]) AS
(
SELECT [ID]
FROM
(
SELECT [ID]
,[Name]
,[Value]
FROM Data
) DataSource
PIVOT
(
MAX([Value]) FOR [Name] IN (' + #SQLColumns+ ')
) PVT
WHERE ' + #SQLFilterColumns + '
)
SELECT DT.[ID]
,DT.[Name]
,DT.[Value]
FROM Data DT
INNER JOIN DataSource DS
ON DT.[ID] = DS.[ID]
'
EXECUTE sp_executesql #SQLStatement
DROP TABLE Data
DROP TABLE Filter
SET NOCOUNT OFF
GO
Here is an option using a couple of PIVOTs
DECLARE #Data table ([ID] INT, [Name] VARCHAR(12), [Value] VARCHAR(2) )
DECLARE #Filter TABLE ( [Name] VARCHAR(12), [Value] VARCHAR(2) )
INSERT INTO #Data ([ID], [Name], [Value])
VALUES (1, 'productname', 'A')
,(1, 'cost', '20')
,(1, 'active', 'Y')
,(2, 'productname', 'A')
,(2, 'cost', '20')
,(2, 'active', 'N')
,(3, 'productname', 'B')
,(3, 'cost', '20')
,(3, 'active', 'Y')
,(4, 'productname', 'A')
,(4, 'cost', '20')
,(4, 'active', 'Y')
INSERT INTO #Filter ([Name], [Value])
VALUES ('productname', 'A')
,('active', 'Y');
SELECT *
FROM ( SELECT *
FROM (select [ID], [Name], [value] from #Data) as s
PIVOT
( MAX([value]) FOR [name] in ( [productname], [active])
) as pvt) B
INNER JOIN
( SELECT *
FROM (select [name], [value] from #Filter) as f
PIVOT
( MAX([value]) for [Name] IN ([productname], [active])
) AS fpvt
) F
ON F.active = b.active and f.productname = b.productname
By doing a PIVOT on the DATA table and then on the FILTER table, it allows them to be lined up for an inner join. This returns the records that match within both,