Find order by based on column value not column name - sql

I have a query where I want to order based on column value not column name i.e.
Suppose I have a column "Description" in table and in my sql I have like condition as
Select * from tableName
where Description like '%Bombay%'
or Description like '%Hotel%' like Description like '%Rent%'
I want to order the records if column Description have all the three values or two values or one value i.e. if all the three values are in Description column it should be in at top
Is it possible in sql ?

drop table if exists dbo.tableName;
create table dbo.tableName (
ID int primary key
, Description varchar(100)
);
insert into dbo.tableName (ID, Description)
values (1, 'Hotel Bombay Rent')
, (2, 'Hotel Bombay')
, (3, 'Hotel')
, (4, 'Aparment');
select
t.ID
, t.Description
from dbo.tableName t
order by (case when t.Description like '%Hotel%' then 1 else 0 end)
+ (case when t.Description like '%Bombay%' then 1 else 0 end)
+ (case when t.Description like '%Rent%' then 1 else 0 end) desc

Related

Limit Number of elements in a string aggregation query

I have below table and string aggregation using XML:
CREATE TABLE TestTable ([ID] INT, [Name] CHAR(1))
INSERT INTO TestTable ([ID],[Name]) VALUES (1,'A')
INSERT INTO TestTable ([ID],[Name]) VALUES (2,'B')
INSERT INTO TestTable ([ID],[Name]) VALUES (3,'C')
INSERT INTO TestTable ([ID],[Name]) VALUES (1,'D')
INSERT INTO TestTable ([ID],[Name]) VALUES (1,'E')
INSERT INTO TestTable ([ID],[Name]) VALUES (2,'F')
INSERT INTO TestTable ([ID],[Name]) VALUES (3,'G')
INSERT INTO TestTable ([ID],[Name]) VALUES (4,'H')
SELECT
[ID],
STUFF((
SELECT ' ' + [Name]
FROM TestTable
WHERE (ID = Results.ID)
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
,1,2,'') AS Names
FROM TestTable Results
GROUP BY ID
I get below result
ID Names
1 A D E
2 B F
3 C G
4 H
However i have requirement to limit number of Names to two, if its more than two, it should split to next row, Something like below. Here for ID=1, there were 3 Names, so 3rd name split into next row. How can i achieve this requirement
ID Names
1 A D
1 E
2 B F
3 C G
4 H
Thanks
It sounds like you want conditional aggregation, with up to two name columns per row. You can do this using row_number() and some arithmetic:
select id,
max(case when seqnum % 2 = 1 then name end) as name1,
max(case when seqnum % 2 = 0 then name end) as name2
from (select t.*,
row_number() over (partition by id order by name) as seqnum
from testtable t
) t
group by id, ceiling(seqnum / 2.0)
order by id, min(seqnum);
Here is a db<>fiddle.
I should note that you can concatenate these into a single column. I don't see a reason to do so, because you know the maximum number on each row.

Getiing multiple rows as output using case statement in sql

I have a table,
id category column1 column2 column3
1 1 val1a val1b val1c
2 2 val2a val2b val2c
3 3 val3a val3b val3c
from which I need to select columns based on multiple conditions something like below.
SELECT id, category, column1, column2, column3
FROM table
WHERE id = #id
AND category IN (
select case when (#input1='Yes' AND #input2='Yes') then (select category from table where category in ('1','2'))
when (#input1='Yes' AND #input2='No') then (select category from table where category ='1')
when (#input1='No' AND #input2='Yes') then (select category from table where category ='2')
else ''
end as category)
END
Input values #input1 and #input2 are grabbed from another table, need to select and output rows with category in ('1','2') according to above condition.
What I need -
if input1=Yes and input2=Yes output rows with category in ('1','2')
if input1=Yes and input2=No output rows with category in ('1')
if input1=No and input2=Yes output rows with category in ('2')
if input1=No and input2=No output rows with category in ('')
Does case statement output multiple values? Need help.
check out the code below, you don't need to use CASE WHEN, just use where condition combinations will do the trick.
create table [Test] ( id int, category nvarchar(10));
insert [Test] values(1,'1');
insert [Test] values(2,'2');
insert [Test] values(3,'1');
insert [Test] values(4,'2');
declare #input1 varchar(10) = 'Yes'
declare #input2 varchar(10) = 'No'
SELECT id, category
FROM [Test]
WHERE
(
( #input1 = 'Yes' and category ='1')
or
( #input2 = 'Yes' and category ='2')
)
If you wanted to use in, you could use:
where id = #id and
category in ( (case when #input1 = 'Yes' then 1 end),
(case when #input2 = 'Yes' then 2 end)
)
The default value for the case is NULL and that will fail any comparison.
Also, note that I removed the single quotes around '1' and '2'. These look like numbers, so I assume that category is a number. Quotes should only be used around string and date constants.
Maybe this:
SELECT id, category, column1, column2, column3
FROM table
WHERE id = #id
AND category IN
(
select category
from table
where
(
category = '1'
AND
#input1='Yes'
)
OR
(
category = '2'
AND
#input1='Yes'
)
)
or this:
SELECT id, category, column1, column2, column3
FROM table
WHERE id = #id
AND
(
(
#input1='Yes' AND #input2='Yes' AND category IN (select category from table where category in ('1','2')
)
OR
(
#input1='Yes' AND #input2='No' AND category IN (select category from table where category ='1')
)
OR
(
#input1='No' AND #input2='Yes' AND category IN (select category from table where category ='2')
)
)
I would suggest you to form a mapping table and leverage it in the SELECT query. It will result in simplified code and more clear approach.
;WITH CTE_MappingTable AS
(
SELECT *
FROM
(
values
('Yes','Yes',1),
('Yes','Yes',2),
('Yes','No',1),
('No','Yes',2)
) as t(input1,input2,category)
)
SELECT id, category, column1, column2, column3
FROM table as t
INNER JOIN CTE_MappingTable as c
ON c.Category = t.Category
WHERE id = #id AND c.input1 = #input1 AND c.input2 = #input2

Constructing single select statement that returns order depends on the value of a column in SQL Server

Table1
Id bigint primary key identity(1,1)
Status nvarchar(20)
Insert dummy data
Insert into Table1 values ('Open') --1
Insert into Table1 values ('Open') --2
Insert into Table1 values ('Grabbed') --3
Insert into Table1 values ('Closed') --4
Insert into Table1 values ('Closed') --5
Insert into Table1 values ('Open') --6
How would I construct a single select statement which orders the data where records with 'Grabbed' status is first, followed by 'Closed', followed by 'Open' in SQL Server
Output:
Id Status
3 Grabbed
4 Closed
5 Closed
1 Open
2 Open
6 Open
I think you need something like this:
select *
from yourTable
order by case when Status = 'Grabbed' then 1
when Status = 'Closed' then 2
when Status = 'Open' then 3
else 4 end
, Id;
[SQL Fiddle Demo]
Another way is to using CTE like this:
;with cte as (
select 'Grabbed' [Status], 1 [order]
union all select 'Closed', 2
union all select 'Open', 3
)
select t.*
from yourTable t
left join cte
on t.[Status] = cte.[Status]
order by cte.[order], Id;
[SQL Fiddle Demo]
This could be done much better with a properly normalized design:
Do not store your Status as a textual content. Just imagine a typo (a row with Grabed)...
Further more a lookup table allows you to add side data, e.g. a sort order.
CREATE TABLE StatusLookUp(StatusID INT IDENTITY PRIMARY KEY /*you should name your constraints!*/
,StatusName VARCHAR(100) NOT NULL
,SortRank INT NOT NULL)
INSERT INTO StatusLookUp VALUES
('Open',99) --ID=1
,('Closed',50)--ID=2
,('Grabbed',10)--ID=3
CREATE TABLE Table1(Id bigint primary key identity(1,1) /*you should name your constraints!*/
,StatusID INT FOREIGN KEY REFERENCES StatusLookUp(StatusID));
Insert into Table1 values (1) --1
Insert into Table1 values (1) --2
Insert into Table1 values (3) --3
Insert into Table1 values (2) --4
Insert into Table1 values (2) --5
Insert into Table1 values (1) --6
SELECT *
FROM Table1 AS t1
INNER JOIN StatusLookUp AS s ON t1.StatusID=s.StatusID
ORDER BY s.SortRank;
I find that the simplest method uses a string:
order by charindex(status, 'Grabbed,Closed,Open')
or:
order by charindex(',' + status + ',', ',Grabbed,Closed,Open,')
If you are going to put values in the query, I think the easiest way uses values():
select t1.*
from t1 left join
(values ('Grabbed', 1), ('Closed', 2), ('Open', 3)) v(status, priority)
on t1.status = v.status
order by coalesce(v.priority, 4);
Finally. This need suggests that you should have a reference table for statuses. Rather than putting the string name in other tables, put an id. The reference table can have the priority as well as other information.
Try this:
select Id,status from tablename where status='Grabbed'
union
select Id,status from tablename where status='Closed'
union
select Id,status from tablename where status='Open'

SQL Stored Procedure adding to statement

Issue:
I want to pass a value say #Test into a stored procedure and I know that when #Test is certain values all is good. However I want to filter several values in the Table/Gridview under one #Test value.
i.e. User searches for "Red" I want to show "Red" "Pink" etc...
I am sure there must be hunderds of examples but I have searched and not found them. I have tried BEGIN and also IF statements.
If .net I would add a If #Text = 'Pink' Then
sql= sql & ... statement...
So far I have...
SELECT * FROM TblColours
WHERE
Room LIKE '%' + #sRoom + '%'
or Colours LIKE '%' + #sColours + '%'
IF #sColours = 'Pink'
or Colours = 'Red'
or Colours = 'Shade of Pink'
END
I agree with Andrew, that it would be much easier to store the colours and their groupings in separate tables - it might look something like the below (two new tables, #Colours and #Colourgroups are used).
-- SETUP TABLES AND VALUES
----------------------------------------------------------------------------------------------
IF OBJECT_ID('tempdb.dbo.#Colours') IS NOT NULL DROP TABLE #Colours
IF OBJECT_ID('tempdb.dbo.#TblColours') IS NOT NULL DROP TABLE #TblColours
IF OBJECT_ID('tempdb..#ColourGroups') IS NOT NULL DROP TABLE #ColourGroups
CREATE TABLE #Colours
( Id INT NOT NULL PRIMARY KEY CLUSTERED
,GroupId INT NOT NULL
,Name VARCHAR(50) NOT NULL)
CREATE TABLE #ColourGroups
( Id INT NOT NULL PRIMARY KEY CLUSTERED
,Name VARCHAR(50) NOT NULL)
CREATE TABLE #TblColours
( Room VARCHAR(50) NOT NULL
,ColourId INT NOT NULL)
INSERT #Colours
SELECT * FROM
(SELECT 1 AS Id, 1 AS GroupId, 'Red' AS Name UNION
SELECT 2 AS Id, 2 AS GroupId, 'Orange' AS Name UNION
SELECT 3 AS Id, 3 AS GroupId, 'Yellow' AS Name UNION
SELECT 4 AS Id, 1 AS GroupId, 'Pink' AS Name UNION
SELECT 5 AS Id, 1 AS GroupId, 'Scarlet' AS Name UNION
SELECT 6 AS Id, 1 AS GroupId, 'Rose' AS Name) AS SomeRandomColours
ORDER BY Id
INSERT #ColourGroups
SELECT * FROM
(SELECT 1 AS Id, 'Red' AS Name UNION
SELECT 2 AS Id, 'Orange' AS Name UNION
SELECT 3 AS Id, 'Yellow' AS Name) AS SomePossibleGroups
ORDER BY Id
INSERT #TblColours Values ('Gail''s Bedroom', 6)
INSERT #TblColours Values ('The Horrid Bathroom', 2)
INSERT #TblColours Values ('The Main DrawingRoom', 5)
INSERT #TblColours Values ('Paul and Barbara''s Bedroom', 4)
INSERT #TblColours Values ('Paul''s Study', 1)
----------------------------------------------------------------------------------------------
-- Include Derived colour working back from the group if you want to find all the colours in
-- the same group as your search.
DECLARE
#sRoom VARCHAR(50) = 'Barbara'
,#sColours VARCHAR(50) = 'Pink'
SELECT DISTINCT
Room.Room
,Colour.Name
FROM #TblColours AS Room
INNER JOIN #Colours AS Colour ON Room.ColourId = Colour.Id
INNER JOIN #ColourGroups AS ColourGroup ON Colour.GroupId = ColourGroup.Id
INNER JOIN #Colours AS DerivedColour ON ColourGroup.Id = DerivedColour.GroupId
WHERE
Room LIKE '%' + #sRoom + '%'
OR Colour.Name = #sColours
OR ColourGroup.Name = #sColours
OR DerivedColour.Name = #sColours

sql query serial number

I have written a stored procedure in SQL Server 2000. I want a serial number for output table.
So when I run this stored proc I get this error:
An explicit value for the identity column in table
'#tmpSearchResults1' can only be specified when a column list is used
and IDENTITY_INSERT is ON.
I have tried with set IDENTITY_INSERT #tmpSearchResults1 on
Create Procedure dbo.usp_mobile_All_KeyWord(#searchkey varchar(30))
AS
CREATE TABLE #tmpSearchResults
(
property_id varchar(255),
property_number varchar(255),
auction_date_reason varchar(255)
)
INSERT INTO #tmpSearchResults
SELECT
p.property_id, p.property_number, p.auction_date_reason
FROM
Pr p
INNER JOIN
Au a ON p.auction_id = a.auction_id
INNER JOIN
PrAdd pa ON p.property_id = pa.property_id
INNER JOIN state AS s ON s.state_id=pa.state
where
(
(p.archive = 'N'
AND
a.show_on_site = 'Y'
AND
(
(
((p.auction_date >= CONVERT(datetime, CONVERT(varchar, GETDATE(), 103), 103) and (p.auction_date_reason is null or p.auction_date_reason = ''))
or
(p.auction_date <= CONVERT(datetime, CONVERT(varchar, GETDATE(), 103), 103) and ( p.auction_date_reason = 'Accepting Offers' )))
and
pa.property_address_type_id = 1 )) )
and
(state_abbreviation=#searchkey or s.state_name like '%'+''+ #searchkey +''+'%' or city like '%'+''+ #searchkey +''+'%' or pa.address1 like '%'+''+ #searchkey +''+'%'
or pa.address2 like '%'+''+ #searchkey +''+'%')
)
)
CREATE TABLE #tmpSearchResults1
(
i1 int identity,
property_id varchar(255),
property_number varchar(255),
auction_date_reason varchar(255)
)
insert into #tmpSearchResults1
select
property_id ,
property_number,
auction_date_reason
from #tmpSearchResults
order by
case when charindex(#searchkey,state) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,statename) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,city) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,address2) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,address1) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,short_description) >0 then 1000 else 0 end desc
select * from #tmpSearchResults1
Plz do help me
The error code is very very very clear.
The relevant portion is ...when a column list is used....
You need to specify your column list in the INSERT statement.
INSERT INTO #tmpSearchResults
(i1,
property_id,
property_number,
auction_date_reason)
SELECT
p.property_id, p.property_number, p.auction_date_reason
FROM...
First, there is a comma too much in the SELECT part of your second statement:
insert into #tmpSearchResults1
select
property_id ,
property_number,
auction_date_reason , <-- THIS ONE!!
from #tmpSearchResults
The last column of a SELECT statement must be without a comma.
So this would be correct:
insert into #tmpSearchResults1
select
property_id ,
property_number,
auction_date_reason
from #tmpSearchResults
Second, did you read this part of the error message?
An explicit value [...] can only be specified when a column list is used
The "column list" part means that you have to specify the columns in the INSERT part:
insert into #tmpSearchResults1
(property_id, property_number, auction_date_reason)
select
property_id ,
property_number,
auction_date_reason
from #tmpSearchResults
You can get away with not specifying the columns when the number of columns in the SELECT statement is the same as in the table in which they should be inserted (and if the data types match).
If one of these conditions is not met, you need to specify the columns because otherwise SQL Server doesn't know which value to insert into which column.