Get the column names matching a multiple column search - sql-server

For an application, I need to show search results based upon multiple columns. Searching in multiple columns is not that hard, but I also want to know which column(s) the search query matches the text.
Imagine following 'Blabla' table:
---------------------------------------------------------------------------------------
| column1 | column2 | column 3 |
---------------------------------------------------------------------------------------
| Animals are beautiful | Some text regarding music | Vague statement about politics |
---------------------------------------------------------------------------------------
| Music is not his thing | Green is a color | Random gibberish about music |
---------------------------------------------------------------------------------------
Searching for the word 'music' would be as simple as:
SELECT * FROM Blabla WHERE column1 LIKE '%music%' OR column2 LIKE '%music%' OR column2 LIKE '%music%';
But is there a way in SQL to show that matching columns would be column2 for row 1 and column1 + column3 for row 2?

You could use a CASE statement:
SELECT CASE WHEN column1 LIKE '%music%' THEN 'Column1' ELSE '' END AS col1match,
CASE WHEN column2 LIKE '%music%' THEN 'Column2' ELSE '' END AS col2match,
CASE WHEN column3 LIKE '%music%' THEN 'Column3' ELSE '' END AS col3match
FROM Blabla

That would be
select
column1,
column2,
column3,
case
when column1 like '%music%' then 'column1'
when column2 like '%music%' then 'column2'
when column3 like '%music%' then 'column3'
else ''
end as [column]
from Blabla where column1 like '%music%' or column2 like '%music%' or column3 like '%music%'
Not sure about how performant this actually is.

Yes, you can use CASE EXPRESSION for indication columns :
SELECT s.* FROM (
SELECT t.*,
CASE WHEN t.column1 LIKE '%music%' THEN 1 ELSE 0 as col_1_ind,
CASE WHEN t.column2 LIKE '%music%' THEN 1 ELSE 0 as col_2_ind,
CASE WHEN t.column3 LIKE '%music%' THEN 1 ELSE 0 as col_3_ind
FROM Blabla t) s
WHERE 1 IN(s.col_1_ind,s.col_2_ind,s.col_3_ind)

try this,
declare #t table(column1 varchar(100), column2 varchar(100),column3 varchar(100))
insert into #t values
('Animals are beautiful','Some text regarding music','Vague statement about politics')
,('Music is not his thing','Green is a color','Random gibberish about music')
;With CTE as
(
select column1,column2,column3,ROW_NUMBER()over(order by (select null))rn from #t
)
select case when column1 LIKE '%music%' then 'column1 in row'+ cast(rn as varchar) end
,case when column2 LIKE '%music%' then 'column2 in row'+ cast(rn as varchar) end
,case when column3 LIKE '%music%' then 'column3 in row'+ cast(rn as varchar)
end
from cte

Related

Get the max number in a varchar column SQL Server

I have a varchar column which holds comma separated numbers.
I want to fetch the max number in that column.
+-------------------+--------------+
| reference_no | Name |
+-------------------|--------------+
| 17530, 20327 | John |
| , 14864 | Smith |
| 8509 | Michael |
| 14864, 17530 | Kelly |
+-------------------+--------------+
So, in the above column (reference_no) example the output should be 20327.
Then I have to select the row which contains this number.
Assuming NOT 2016+
If you have no more than 4 values in reference_no in any particular row, then perhaps parsename()
If more than 4, you may need to fix the data or use a split/parse function.
Example
Select MaxValue = max(V)
From YourTable A
Cross Apply ( values (replace([reference_no],',','.')) ) B(S)
Cross Apply ( values (try_convert(int,parsename(S,1)))
,(try_convert(int,parsename(S,2)))
,(try_convert(int,parsename(S,3)))
,(try_convert(int,parsename(S,4)))
) C(V)
Returns
MaxValue
20327
try the following:
declare #tab table (reference_no varchar(max), [Name] varchar(100))
insert into #tab
select '17530, 20327','John' union
select ', 14864 ','Smith' union
select '8509 ','Michael' union
select '14864, 17530','Kelly'
create table #final (val int)
insert into #final
SELECT Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT reference_no reference_no,
CAST ('<S>' + REPLACE(reference_no, ',', '</S><S>') + '</S>' AS XML) AS String
FROM #tab) AS A CROSS APPLY String.nodes ('/S') AS Split(a);
select * from #tab where reference_no like '%'+ (select convert(varchar(100), max(val)) from #final) + '%'
drop table #final

SSMS / TSQL - Insert multiple records for every record found in query

I want to insert multiple records (two to be specific) with a unique ID for Column 1 (in both records created) for every record that matches a specific query criteria . The rest of the values for the insert should be pulled from the respective columns on the query. In the first insert Column2 will be the original value from Column1, and on the second insert Column2 will be the original value from Column2.
Ideally, what I'm after is:
FIND RECORDS THAT MEETS CRITERIA
FOR EACH RECORD
GENERATE GUID
INSERT TWO NEW RECORDS WITH GUID AS COLUMN1, AND REMAINING COULMNS FROM
CURRENT RECORD FOUND
RECORDS
123 abc 3 4 5
456 def 6 7 8
RECORD 1
123 abc 3 4 5
NEW RECORDS AFTER INSERTS
UID1 123 3 4 5
UID1 abc 3 4 5
ROW 2
456 def 6 7 8
NEW RECORDS AFTER INSERTS
UID2 456 6 7 8
UID2 def 6 7 8
The below INSERT SELECT FROM handles exactly what I want to do but only for a single insert per record found.
INSERT INTO table1
(
Column1,
Column2,
Column3
Column4
Column5
)
SELECT
NEWID(), -- unique ID
Column2, -- or Column1 based on which insert we are doing
Column3, -- always column 3
Column4, --always column 4
Column5 -- always column 5
FROM
table1
WHERE Column1 IS NOT NULL
AND Column1 != Column4
Is there an easy way to do this via TSQL? I need it to run in bulk, for a potential of thousands of records meeting the query conditions.
WITH xQ(UUID,Column2,Column3,Column4,Column5) AS
(
SELECT
NEWID(),
Column1,
Column2,
Column3,
Column4,
Column5
FROM
table1
WHERE Column1 IS NOT NULL
AND Column1 != Column4
)
INSERT INTO table1
(
Column1,
Column2,
Column3,
Column4,
Column5
)
SELECT
UUId,
Column1,
Column3,
Column4,
Column5
FROM xQ
UNION
SELECT
UUId,
Column2,
Column3,
Column4,
Column5
FROM xQ
Here's a possibility. First use your query that generates the first set of rows and insert them into a temp table.
Rextester Demo
SELECT
NEWID() AS [uid], -- unique ID
column1,
Column2, -- or Column1 based on which insert we are doing
Column3, -- always column 3
Column4, --always column 4
Column5 -- always column 5
INTO #temp
FROM
table1
WHERE Column1 IS NOT NULL
AND Column1 != Column4
Now using that temp table we can do a UNION with the same table to generate the second set of rows and insert them into table1.
INSERT INTO table1
SELECT
[uid] AS Column1
, CAST(column1 AS NVARCHAR(3)) AS Column2
, column3
, column4
, column5
FROM #temp
UNION ALL
SELECT
[uid] AS Column1
, column2
, column3
, column4
, column5
FROM #temp
ORDER BY Column1
DROP TABLE #temp

SQL Server order by case

I want to create a fourth column with this query:
select * from (select ID, column0, column1, column2, column3 = Case when
column2 = '' then column1 else column2 end, row_number() over(partition by
column0 order by [column3]) as column4 from myTable) ti
But this error appears:
Invalid column name 'column3'.
I want this result: (red marked column):
you need to use order by from outside of subquery as below:
Select *, row_number() over(partition by
column3 order by [Id]) as column4
from (select ID, column0, column1, column2, column3 = Case when
column2 = '' then column1 else column2 end
from myTable) ti
For your 4th column in image you need to partition by column3 order by id. If you do Partition by column0 then you will get all 1's
This way it will work:
select *, row_number() over(partition by
column0 order by [column3]) as column4 from
(select ID, column0, column1, column2, column3 = Case when
column2 = '' then column1 else column2 end from myTable) ti

Syntax error in pivoting a SQL Server table using VARCHAR columns

I have a table (~50m rows) like below in SQL Server:
PId CustomColumnName CustomColumnValue
1 PropertyA 1
1 PropertyB B
1 PropertyC C
2 PropertyA 1.5
2 PropertyB BB
2 PropertyC CC
3 PropertyD D1
3 PropertyA 2.0
I'd like to PIVOT that table to look something like this:
PId PropertyA PropertyB PropertyC PropertyD
1 1 B C NULL
2 1.5 BB CC NULL
3 2.0 NULL NULL D1
I know that SQL Server has PIVOT function, so I wrote something like this:
SELECT *
FROM
(
SELECT [PId], [CustomColumnName], [CustomColumnValue]
FROM [myTable]
) AS src
PIVOT
(
MAX([CustomColumnValue]) -- Not sure how to aggregate VARCHAR data here
FOR [CustomColumnName] IN ('PropertyA', 'PropertyB', 'PropertyC', 'PropertyD')
) AS pvt
But I got Incorrect syntax near 'PropertyA' error. I'm not sure if what I'm trying to do is even possible with the PIVOT function of SQL Server (because I don't think I can aggregate [CustomColumnValue], which is of VARCHAR type). If using PIVOT is not feasible in my use case, is there an efficient, alternative way to achieve what I'm trying to do?
Thank you in advanced for your suggestions/answers!
--remove the Single quotes you will get desired Result set
;With cte(PId, CustomColumnName,CustomColumnValue)
AS
(
SELECT 1,'PropertyA','1' Union all
SELECT 1,'PropertyB','B' Union all
SELECT 1,'PropertyC','C' Union all
SELECT 2,'PropertyA','1.5' Union all
SELECT 2,'PropertyB','BB' Union all
SELECT 2,'PropertyC','CC' Union all
SELECT 3,'PropertyD','D1' Union all
SELECT 3,'PropertyA','2.0'
)
SELECT *
FROM
(
SELECT [PId], [CustomColumnName], [CustomColumnValue]
FROM cte
) AS src
PIVOT
(
MAX([CustomColumnValue])
FOR [CustomColumnName] IN (PropertyA, PropertyB, PropertyC, PropertyD)
) AS pvt
You can generate the same Result Set using Dynamic Pivot.it is as below
IF OBJECT_ID('tempdb..#temp') IS NOT NULL
Drop table #temp
;With cte(PId, CustomColumnName,CustomColumnValue)
AS
(
SELECT 1,'PropertyA','1' Union all
SELECT 1,'PropertyB','B' Union all
SELECT 1,'PropertyC','C' Union all
SELECT 2,'PropertyA','1.5' Union all
SELECT 2,'PropertyB','BB' Union all
SELECT 2,'PropertyC','CC' Union all
SELECT 3,'PropertyD','D1' Union all
SELECT 3,'PropertyA','2.0'
)
SELECT * INTO #temp FROM cte
Declare
#Sql nvarchar(max),
#dynamicCol nvarchar(max)
--Create columns Dynamically
SELECT #dynamicCol=STUFF((SELECT DISTINCT ', '+ QUOTENAME(CustomColumnName )
From #temp For XML PATH ('')),1,1,'')
--SELECT #dynamicCol
SET #Sql='
SELECT [PId] ,'+ #dynamicCol +' From
(
SELECT [PId], [CustomColumnName], [CustomColumnValue] From
#temp
)AS Src
PIVOT
(
MAX([CustomColumnValue]) For [CustomColumnName] IN ('+#dynamicCol+')
)
AS Pvt'
PRINT #Sql
EXEC(#Sql)
Remove the quotes.
SELECT *
FROM
(
SELECT [PId], [CustomColumnName], [CustomColumnValue]
FROM [myTable]
) AS src
PIVOT
(MAX([CustomColumnValue])
FOR [CustomColumnName] IN ([PropertyA], [PropertyB], [PropertyC], [PropertyD])
) AS pvt
GO
PId | PropertyA | PropertyB | PropertyC | PropertyD
--: | :-------- | :-------- | :-------- | :--------
1 | 1 | B | C | null
2 | 1.5 | BB | CC | null
3 | 2.0 | null | null | D1
dbfiddle here
You require to use quotename of columns
SELECT *
FROM
(
SELECT [PId], [CustomColumnName], [CustomColumnValue]
FROM [myTable]
) AS src
PIVOT
(
MAX([CustomColumnValue]) -- Not sure how to aggregate VARCHAR data here
FOR [CustomColumnName] IN ([PropertyA], [PropertyB], [PropertyC], [PropertyD]) --provide in squarebrackets if generating dynamic then use quotename() function of sql server
) AS pvt

MS Sql Server Pivot two columns

I can not seem to find an example of this type of pivot if it is possible.
+---------+---------+
| column1 | column2 |
+---------+---------+
| 10 | A |
| 20 | B |
| 30 | C |
+---------+---------+
I would like my query to return
+----+----+----+
| A | B | C |
+----+----+----+
| 10 | 20 | 30 |
+----+----+----+
I would like to do it without creating a view or dynamic table.
I have been trying the pivot option but I am having a problem understanding how to use dynamic values from the query. My query is:
Select column1, column3 + '_' + column4 as column2
from table1
Now I want to use the column2 values as columns names with the associated column1 values.
You can use the PIVOT function:
select A, B, C
from yourtable
pivot
(
max(column1) -- column values
for column2 in (A, B, C) -- new column names
) p;
If you have dynamic columns then you will have to use dynamic SQL and implement it inside of a stored procedure. The code would be similar to:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
-- create the list of columns for the pivot
select #cols = STUFF((SELECT ',' + QUOTENAME(column2)
from
(
select column3 + '_' + column4 as column2
from table1
) d
group by column2
order by column2
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ' + #cols + '
from
(
Select column1, column3 + ''_'' + column4 as column2
from table1
) x
pivot
(
max(column1)
for column2 in (' + #cols + ')
) p '
exec sp_executesql #query;
select case when column2 = 'A' then column1 end as A,
case when column2 = 'B' then column1 end as B,
case when column2 = 'C' then column1 end as C
from your_table

Resources