Select Rows Where A Column Contains Any Result From A SubQuery - sql

If have a table that contains a column of concatenated data using a delimiter i.e. 11111_22222_33333 (I know this is bad practice, but that's the data I have to work with)
I need to write a query that returns all rows that contain specific values of 22222 where the specific values are the result of a sub query.
So, what I am doing is follows...
SELECT * FROM myTable WHERE myColumn IN (SELECT [Name] FROM subTable)
This runs but doesnt return any results as it's specifically matching 1111_2222_3333 to 2222. So what I need is a way of using a LIKE or something similar
SELECT * FROM myTable WHERE myColumn LIKE (SELECT [NAME] FROM subTable)
gives the error
Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows
=, !=, <, <= , >, >= or when the subquery is used as an expression.
How would this be accomplished please? I am using Sql Server 2008 R2 to develop, but the solution needs to also be compatible with Server 2005

Your subquery is returning more than one value and LIKE will not work with subquery, what you need to use is EXISTS here try this
SELECT * FROM myTable a
WHERE EXISTS (SELECT 1 FROM subTable b
WHERE a.myColumn LIKE '%' + b.[NAME] + '%')

SELECT
t1.*
FROM myTable t1
join (
SELECT distinct [Name] FROM subTable
) x
on t1.myColumn like '%' + x.[name] + '%'

You can use a JOIN with the LIKE clause to get the result:
select *
from mytable t
inner join subtable s
on t.mycolumn like '%'+s.name+'%'
See SQL Fiddle with Demo

Related

SQL - Run Select Statement Based On Where Query

Hi i want to create a query which does the following. When the paramter 25 is selected it only runs part A of the query, if any other number is selected run both Table A and B select queries.
Example Below:
DECLARE #Type varchar (200)
select * from
(SELECT sort_code FROM dbo.Test 1
WHERE FUNDING_YEAR = 26)
union
(SELECT sort_code FROM dbo.Test 2
WHERE FUNDING_YEAR = 26)
Where case when #Type = 25 then select * from table2 else table 1
You just need to reference the variable in the WHERE clause
SELECT *
FROM TableA
WHERE #Type = 25
UNION
SELECT *
FROM TableB
The query above will always select everything in TableB and will only select everything in TableA when the variable is equal to 25.
Since you are using SSRS, what I would do is write the query to return all of the rows and then apply a filter in the SSRS report when the Paramater is 25. I wouldn't pass a paramater value to the SQL side unless it greatly reduces the run time of the query.
(I would have put this in a comment.)

SQL Subquery returned more than 1 value. This is not permitted when the subquery

I have this query:
SELECT *
FROM Schedule_OverdueTasks
WHERE Job_No LIKE (
SELECT DISTINCT AREA_ID
FROM V_CONSTAT_PROJ_DATES
WHERE AREA_DESC IN ('aaa', 'bbb') + '%'
but this gives me this error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
When I run my query like so, I get no errors, because there is only 1 AREA_I
SELECT *
FROM Schedule_OverdueTasks
WHERE Job_No LIKE (
SELECT DISTINCT AREA_ID
FROM V_CONSTAT_PROJ_DATES
WHERE AREA_DESC = 'aaa') + '%'
I have tried redoing my query like so:
SELECT *
FROM Schedule_OverdueTasks
INNER JOIN V_CONSTAT_PROJ_DATES
ON V_CONSTAT_PROJ_DATES.JOB_NUMBER = Schedule_OverdueTasks.Job_No
WHERE V_CONSTAT_PROJ_DATES.AREA_DESC IN ('aaa', 'bbb')
But I do not get the same number of results. What am I doing wrong?
I would recommend that you use exists:
SELECT ot.*
FROM Schedule_OverdueTasks ot
WHERE EXISTS (SELECT 1
FROM V_CONSTAT_PROJ_DATES pd
WHERE ot.Job_No LIKE pd.area_id + '%' AND
AREA_DESC IN ('aaa', 'bbb')
);
I can't comment so I need to use the answer section, but like takes a scalar data type not a `table valued data type
Meaning you can only compare it to 1 value
so without knowing your data structure the best I would be able to recommend at the moment is
SELECT *
FROM Schedule_OverdueTasks
INNER JOIN (
SELECT DISTINCT AREA_ID
FROM V_CONSTAT_PROJ_DATES
WHERE AREA_DESC = 'aaa'
) vcpd ON Job_No LIKE Area_ID + '%'
Edit:
As Per Gordons answer an exist would be ideal for performance while not changing the result set though the optimizer might interpret this as an exist but better to write what you mean.
Based on your query, it looks like Job_No has additional characters on the end of it and AREA_ID would be the first few characters of Job_No. If AREA_ID is a set length (say 5 characters), you could try this
SELECT * FROM Schedule_OverdueTasks
INNER JOIN V_CONSTAT_PROJ_DATES ON LEFT(Schedule_OverdueTasks.Job_No, 5) = V_CONSTAT_PROJ_DATES.AREA_ID
WHERE V_CONSTAT_PROJ_DATES.AREA_DESC IN ('aaa', 'bbb')
the resultset inside the LIKE operator must return one and only one record since the LIKE operator will be evaluated to return true or false.
Use TOP 1 to avoid the error.
This query will not fail, but as to getting the right results, that is a different matter. You must revise your data and conditions.
SELECT *
FROM Schedule_OverdueTasks
WHERE Job_No LIKE (SELECT TOP 1 AREA_ID
FROM V_CONSTAT_PROJ_DATES
WHERE AREA_DESC IN ('aaa', 'bbb') + '%'
To test the behavior of LIKE run the following query and the same error message will be produced.
SELECT foo
FROM ( SELECT 1 foo
UNION ALL
SELECT 1 foo
) bar
WHERE 1 LIKE ( SELECT 1 foo
UNION ALL
SELECT 2 foo
);

sql server using SUBSTRING with LIKE operator returns no results

I created this CTE that returns first and last names from 2 different tables. I would like to use the CTE to identify all of the records that have the same last names and the first name of one column starts with the same first letter of another column.
This is an example of the results of the CTE. I want the SELECT using the CTE to return only the highlighted results:
;WITH CTE AS
(
SELECT AD.FirstName AS AD_FirstName, AD.LastName AS AD_LastName, NotInAD.FirstName As NotInAD_FirstName, NotInAD.LastName As NotInAD_LastName
FROM PagingToolActiveDirectoryUsers AD JOIN
(
SELECT FirstName, LastName
FROM #PagingUsersParseName
EXCEPT
SELECT D.FirstName, D.LastName
FROM PagingToolActiveDirectoryUsers D
WHERE D.FirstName <> D.LastName AND D.LastName <> D.LoginName
AND D.LoginName LIKE '%[0-9]%[0-9]%'
) AS NotInAD ON NotInAD.LastName = AD.LastName
)
SELECT *
FROM CTE
WHERE (AD_LastName = NotInAD_LastName) AND (AD_FirstName LIKE ('''' + SUBSTRING(NotInAD_FirstName, 1, 1) + '%'''))
ORDER BY AD_LastName, AD_FirstName;
The result of this query returns no rows.
What am I doing wrong?
Thanks.
You're enclosing the string to be searched for with single-quotes, but it doesn't appear that the data in AD_FirstName has those single-quotes embedded in it. I suggest you replace the first line of the WHERE clause with
WHERE (AD_LastName = NotInAD_LastName) AND (AD_FirstName LIKE (SUBSTRING(NotInAD_FirstName, 1, 1) + '%'))
Best of luck.

SQL Subquery returned more than 1 value

My query causes the following error:
Msg 512, Level 16, State 1, Procedure Item_insupd, Line 17
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Query:
INSERT INTO [Total_Database].[dbo].[Item]
(
ItemID,
ItemNo,
ItemDescription,
Notes,
StandardCost,
SalesGLAccountID,
ItemTypeID,
Backorderable
)
(
SELECT [nr],
[nr],
[Latijn]+' '+[Subgroep]+' '+CAST([nr] as VARCHAR(255)),
[NL]+' '+[Vorm]+' '+[Kenmerk]+' '+[Hoogte],[Inkoopprijs],
(4),
(case when [Productgroep]='PB' then 1 else 5 end),
(1)
FROM [ACCESDATA].[dbo].[Planten]
);
I suspect this to happen because my subquery does not contain a WHERE, unfortunately I do not know how to construct a correct WHERE clause.
I suspect the problem is in this string (line 26 in your code):
IF NOT (EXISTS (SELECT G.GLAccountID FROM GLAccnt G INNER JOIN Inserted I ON G.GLAccountID = I.SalesGLAccountID))
OR ((SELECT I.COGSGLAccountID FROM Inserted I) IS NOT NULL) AND NOT (EXISTS (SELECT G.GLAccountID FROM GLAccnt G INNER JOIN Inserted I ON G.GLAccountID = I.COGSGLAccountID))
It looks like (SELECT I.COGSGLAccountID FROM Inserted I) return more than one row, so you're getting an error.
You're treating inserted as a one row table (for example, you're getting parameters from it like SELECT #ItemNo = I.ItemNo, #ItemDescription = I.ItemDescription FROM Inserted I, but inserted table can have more than one row. So in your case I think you have 3 options - check that there's only 1 row in inserted, rewrite trigger as set-based, or use cursor.
Here's sql fiddle with somewhat similar example.
If you really only want to insert one row, then You just add Where at the end, followed by some predicate (logical statement) that will be true for only one row in the table the query is reading from.
INSERT INTO [Total_Database].[dbo].[Item](ItemID,
ItemNo,ItemDescription,Notes,StandardCost,SalesGLAccountID,
ItemTypeID,Backorderable)
SELECT [nr],[nr],[Latijn]+' '+[Subgroep]+' '+CAST([nr] as VARCHAR(255)),
[NL]+' '+[Vorm]+' '+[Kenmerk]+' '+[Hoogte],[Inkoopprijs],(4),
(case when [Productgroep]='PB' then 1 else 5 end),(1)
FROM [ACCESDATA].[dbo].[Planten]
Where [SomeColumnName] = [some Value];
... but when performing an Insert using a select to generate the rows to be inserted, you just type the Select statement instead of the Values() clause, without surrounding parentheses. I think that because you had the surrounding parentheses, the query processor assumed you wanted that to be a single value. Do you want to only insert one row of data? or a whole set of data rows ?
INSERT INTO [Total_Database].[dbo].[Item]
(
ItemID,
ItemNo,
ItemDescription,
Notes,
StandardCost,
SalesGLAccountID,
ItemTypeID,
Backorderable
) IN
(
SELECT [nr],
[nr],
[Latijn]+' '+[Subgroep]+' '+CAST([nr] as VARCHAR(255)),
[NL]+' '+[Vorm]+' '+[Kenmerk]+' '+[Hoogte],[Inkoopprijs],
(4),
(case when [Productgroep]='PB' then 1 else 5 end),
(1)
FROM [ACCESDATA].[dbo].[Planten]
);

T-SQL Comma delimited value from resultset to in clause in Subquery

I have an issue where in my data I will have a record returned where a column value will look like
-- query
Select col1 from myTable where id = 23
-- result of col1
111, 104, 34, 45
I want to feed these values to an in clause. So far I have tried:
-- Query 2 -- try 1
Select * from mytableTwo
where myfield in (
SELECT col1
from myTable where id = 23)
-- Query 2 -- try 2
Select * from mytableTwo
where myfield in (
SELECT '''' +
Replace(col1, ',', ''',''') + ''''
from myTable where id = 23)
-- query 2 test -- This works and will return data, so I verify here that data exists
Select * from mytableTwo
where myfield in ('111', '104', '34', '45')
Why aren't query 2 try 1 or 2 working?
You don't want an in clause. You want to use like:
select *
from myTableTwo t2
where exists (select 1
from myTable t
where id = 23 and
', '+t.col1+', ' like '%, '+t2.myfield+', %'
);
This uses like for the comparison in the list. It uses a subquery for the value. You could also phrase this as a join by doing:
select t2.*
from myTableTwo t2 join
myTable t
on t.id = 23 and
', '+t.col1+', ' like '%, '+t2.myfield+', %';
However, this could multiply the number of rows in the output if there is more than one row with id = 23 in myTable.
If you observe closely, Query 2 -- try 1 & Query 2 -- try 2 are considered as single value.
like this :
WHERE myfield in ('111, 104, 34, 45')
which is not same as :
WHERE myfield in ('111', '104', '34', '45')
So, If you intend to filter myTable rows from MyTableTwo, you need to extract the values of fields column data to a table variable/table valued function and filter the data.
I have created a table valued function which takes comma seperated string and returns a table value.
you can refer here T-SQL : Comma separated values to table
Final code to filter the data :
DECLARE #filteredIds VARCHAR(100)
-- Get the filter data
SELECT #filteredIds = col1
FROM myTable WHERE id = 23
-- TODO : Get the script for [dbo].[GetDelimitedStringToTable]
-- from the given link and execute before this
SELECT *
FROM mytableTwo T
CROSS APPLY [dbo].[GetDelimitedStringToTable] ( #filteredIds, ',') F
WHERE T.myfield = F.Value
Please let me know If this helps you!
I suppose col is a character type, whose result would be like like '111, 104, 34, 45'. If this is your situation, it's not the best of the world (denormalized database), but you can still relate these tables by using character operators like LIKE or CHARINDEX. The only gotcha is to convert the numeric column to character -- the default conversion between character and numeric is numeric and it will cause a conversion error.
Since #Gordon, responded using LIKE, I present a solution using CHARINDEX:
SELECT *
FROM mytableTwo tb2
WHERE EXISTS (
SELECT 'x'
FROM myTable tb1
WHERE tb1.id = 23
AND CHARINDEX(CONVERT(VARCHAR(20), tb2.myfield), tb1.col1) > 0
)