How to Merge these 2 Select Statements? - sql-server

How to merge these 2 select statements so that 3 columns are returned?
the first select only returns text values whereas the second select returns a table column value. If the second table returns no value, still the first select should have value and the name column can be null
SELECT 'column1', 'column2'
SELECT Name
FROM [dbo].[TableName]
WHERE ID = #id
Many thanks,

Do you mean something like this:
SELECT 'column1', 'column2', Name
FROM [dbo].[TableName]
WHERE ID = #id
This will return a row for each row with a matching ID in the table.
Update:
This query will do exactly what you want:
IF (SELECT COUNT(Name) FROM [dbo].[TableName] WHERE ID = #id) = 0
BEGIN
SELECT 'column1', 'column2', NULL
END
ELSE
BEGIN
SELECT 'column1', 'column2', Name
FROM [dbo].[TableName]
WHERE ID = #id
END

this would be simpler, no need to duplicate the fixed columns:
DECLARE #name nvarchar(255)
SELECT #name=Name FROM [dbo].[TableName] WHERE ID = #id
SELECT 'column1', 'column2', #name AS 'Name'

You can have one query like this:
SELECT
'column1',
'column2',
(
SELECT Name
FROM [dbo].[TableName]
WHERE ID = #id
) AS 'Name'

If, as seems likely, there can only be at most one match then Andriy or William's solutions are the best. If for some strange reason Id isn't a primary key then the following will do what you want.
SELECT a.column1, a.column2, t.Name
FROM
(
SELECT 'column1' AS column1, 'column2' AS column2
) a
LEFT JOIN [dbo].[TableName] t ON (t.ID = #Id)
I feel kinda dirty....

Related

Query Large (in the millions) Data Faster

I have two tables:
Tbl1 has 2 columns: name and state
Tbl2 has name and state and additional columns about the fields
I am trying to match tbl1 name and state with tbl2 name and state. I have remove all exact matches, but I see that I could match more if I could account for misspelling and name variations by using a scalar function that compares the 2 names and returns an integer showing how close of a match they are (the lower the number returned the better the match).
The issue is that Tbl1 has over 2M records and Tbl2 has over 4M records – it takes about 30sec to just to search one record from Tbl1 in Tbl2.
Is there some way I could arrange the data or query so the search could be completed faster?
Here’s the table structure:
CREATE TABLE Tbl1
(
Id INT NOT NULL IDENTITY( 1, 1 ) PRIMARY KEY,
Name NVARCHAR(255),
[State] VARCHAR(50),
Phone VARCHAR(50),
DoB SMALLDATETIME
)
GO
CREATE INDEX tbl1_Name_indx ON dbo.Tbl1( Name )
GO
CREATE INDEX tbl1_State_indx ON dbo.Tbl1( [State] )
GO
CREATE TABLE Tbl2
(
Id INT NOT NULL IDENTITY( 1, 1 ) PRIMARY KEY,
Name NVARCHAR(255),
[State] VARCHAR(50)
)
GO
CREATE INDEX tbl2_Name_indx ON dbo.Tbl1( Name )
GO
CREATE INDEX tbl2_State_indx ON dbo.Tbl1( [State] )
GO
Here's a sample function that I tested with to try to rule out function complexity:
CREATE FUNCTION [dbo].ScoreHowCloseOfMatch
(
#SearchString VARCHAR(200) ,
#MatchString VARCHAR(200)
)
RETURNS INT
AS
BEGIN
DECLARE #Result INT;
SET #Result = 1;
RETURN #Result;
END;
Here's some sample data:
INSERT INTO Tbl1
SELECT 'Bob Jones', 'WA', '555-333-2222', 'June 10, 1971' UNION
SELECT 'Melcome T Homes', 'CA', '927-333-2222', 'June 10, 1971' UNION
SELECT 'Janet Rengal', 'WA', '555-333-2222', 'June 10, 1971' UNION
SELECT 'Matt Francis', 'TN', '234-333-2222', 'June 10, 1971' UNION
SELECT 'Same Bojen', 'WA', '555-333-2222', 'June 10, 1971' UNION
SELECT 'Frank Tonga', 'NY', '903-333-2222', 'June 10, 1971' UNION
SELECT 'Jill Rogers', 'WA', '555-333-2222', 'June 10, 1971' UNION
SELECT 'Tim Jackson', 'OR', '757-333-2222', 'June 10, 1971'
GO
INSERT INTO Tbl2
SELECT 'BobJonez', 'WA' UNION
SELECT 'Malcome X', 'CA' UNION
SELECT 'Jan Regal', 'WA'
GO
Here's the query:
WITH cte as (
SELECT t1Id = t1.Id ,
t1Name = t1.Name ,
t1State = t1.State,
t2Name = t2.Name ,
t2State = t2.State ,
t2.Phone ,
t2.DoB,
Score = dbo.ScoreHowCloseOfMatch(t1.Name, t2.Name)
FROM dbo.Tbl1 t2
JOIN dbo.Tbl2 t1
ON t1.State = t2.State
)
SELECT *
INTO CompareResult
FROM cte
ORDER BY cte.Score ASC
GO
One possibility would be to add a column with a normalized name used only for matching purposes. You would remove all the white spaces, remove accents, replace first names by abbreviated first names, replace known nicknames by real names etc.
You could even sort the first name and the last name of one person alphabetically in order to allow swapping both.
Then you can simply join the two tables by this normalized name column.
JOIN dbo.Tbl2 t1
ON t1.State = t2.State
You are joining 2Mx4M rows on a max 50 distinct values join criteria. No wonder this is slow. You need to go back to the drawing board and redefine your problem. If you really want to figure out the 'close match' of every body with everybody else in the same state, then be prepared to pay the price...

Unpivot dynamic table columns into key value rows

The problem that I need to resolve is data transfer from one table with many dynamic fields into other structured key value table.
The first table comes from a data export from another system, and has the following structure ( it can have any column name and data):
[UserID],[FirstName],[LastName],[Email],[How was your day],[Would you like to receive weekly newsletter],[Confirm that you are 18+] ...
The second table is where I want to put the data, and it has the following structure:
[UserID uniqueidentifier],[QuestionText nvarchar(500)],[Question Answer nvarchar(max)]
I saw many examples showing how to unpivot table, but my problem is that I dont know what columns the Table 1 will have. Can I somehow dynamically unpivot the first table,so no matter what columns it has, it is converted into a key-value structure and import the data into the second table.
I will really appreciate your help with this.
You can't pivot or unpivot in one query without knowing the columns.
What you can do, assuming you have privileges, is query sys.columns to get the field names of your source table then build an unpivot query dynamically.
--Source table
create table MyTable (
id int,
Field1 nvarchar(10),
Field2 nvarchar(10),
Field3 nvarchar(10)
);
insert into MyTable (id, Field1, Field2, Field3) values ( 1, 'aaa', 'bbb', 'ccc' );
insert into MyTable (id, Field1, Field2, Field3) values ( 2, 'eee', 'fff', 'ggg' );
insert into MyTable (id, Field1, Field2, Field3) values ( 3, 'hhh', 'iii', 'jjj' );
--key/value table
create table MyValuesTable (
id int,
[field] sysname,
[value] nvarchar(10)
);
declare #columnString nvarchar(max)
--This recursive CTE examines the source table's columns excluding
--the 'id' column explicitly and builds a string of column names
--like so: '[Field1], [Field2], [Field3]'.
;with columnNames as (
select column_id, name
from sys.columns
where object_id = object_id('MyTable','U')
and name <> 'id'
),
columnString (id, string) as (
select
2, cast('' as nvarchar(max))
union all
select
b.id + 1, b.string + case when b.string = '' then '' else ', ' end + '[' + a.name + ']'
from
columnNames a
join columnString b on b.id = a.column_id
)
select top 1 #columnString = string from columnString order by id desc
--Now I build a query around the column names which unpivots the source and inserts into the key/value table.
declare #sql nvarchar(max)
set #sql = '
insert MyValuestable
select id, field, value
from
(select * from MyTable) b
unpivot
(value for field in (' + #columnString + ')) as unpvt'
--Query's ready to run.
exec (#sql)
select * from MyValuesTable
In case you're getting your source data from a stored procedure, you can use OPENROWSET to get the data into a table, then examine that table's column names. This link shows how to do that part.
https://stackoverflow.com/a/1228165/300242
Final note: If you use a temporary table, remember that you get the column names from tempdb.sys.columns like so:
select column_id, name
from tempdb.sys.columns
where object_id = object_id('tempdb..#MyTable','U')

How to count number of employees with particular name in this query?

select table1.empname
,table11.empname
,table11.timeordertook
,Table1.saleApproved
,Table1.saleStatus
from Table1, table11
where Table1.empName = Table11.empName
I want to count the number of employees with particular Name in this query How to do this using ms sql query?
As simple as this:
select count(*)
from Table1
inner join table11 on Table1.empName = Table11.empName
where Table1.empName = 'Some name'
Try this:
Just Pass the employee name in the filter
declare #t table (Employee varchar (20))
insert into #t VALUES ('ale')
insert into #t VALUES ('ale')
insert into #t VALUES ('leg')
select count(*)
from #t
where Employee like 'ale'
--OR
--where Employee = 'ale'

Case-When in Group By with Columns of Different Data Types

I want to have a query which dynamically chooses the column to group by.
Suppose I have this table:
I want to see the results grouped by a variable:
Declare #grouBy varchar(50)
Set #grouBy = 'name' -- or 'job' or 'jobCode'
I wrote a query:
SELECT MIN(Name), MIN(job), MIN(jobCode), MAX(salary)
FROM TempTable
GROUP BY
Name,
CASE
WHEN #grouBy = 'job' THEN job
WHEN #grouBy = 'jobCode' THEN jobCode
END
It errors saying:
Conversion failed when converting the varchar value 'programmer' to data type int.
My question is how does the data type matter in this grouping?
I also tried to put the CASE in the SELECT statement but got the following error:
Column '....' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
You need to settle on a common data type for the columns that you are essentially merging in the CASE.
A job value like 'programmer' cannot be converted to an int of course.
Explicitly cast jobCode to job's string data type then. For example, if job's data type is nvarchar(50), use something like this:
Declare #grouBy varchar(50)
Set #grouBy = 'job' -- or 'name' or 'jobCode'
Select
min(Name), min(job), min(jobCode), max(salary)
from TempTable
-- FORNOW: for quick testing/debugging
--from (
-- select 'whatever' as Name, 'a' as job, 1 as jobCode, 1000 as salary
-- union
-- select 'who cares', 'b', 2, 2000) t
Group by Name,
Case
when #grouBy = 'job' then job
when #grouBy = 'jobCode' then cast(jobCode as nvarchar(50))
End
/* FORNOW: quick testing/debugging results
(No column name) (No column name) (No column name) (No column name)
whatever a 1 1000
who cares b 2 2000
*/
You can use IF clause
IF(#groupBy = 'job')
Begin
SELECT
Name, job,min(jobCode), max(salary)s
from TempTable
Group by Name,#grouBy
End
Else If(#groupBy = 'jobCode')
Begin
SELECT
Name, jobCode,min(job), max(salary)s
from TempTable
Group by Name,#grouBy
End
After juggling around the code,
i found optional "Group By" working with columns having different datatypes.
in this method there is no need to CAST() your columns.
1. Simple Example
Declare #groupBy varchar(50)
Set #groupBy = 'name' -- or 'name' or 'jobCode'
Select
min(Name), min(job), min(jobCode), max(salary)
from TempTable
Group by
Case when #groupBy = 'name' then name End,
Case when #groupBy = 'job' then job End,
Case when #groupBy = 'jobCode' then jobCode End
2. And For more aggregate functions in "Select clause" you can use like this.
Select
Case
when #grouBy = 'Name' then min(Name)
when #grouBy = 'job' then count(Name)
when #grouBy = 'jobCode' then count(Name)
End as Name
, max(Salary) as Salary
From TempTable Group by
Case when #groupBy = 'name' then name End,
Case when #groupBy = 'job' then job End,
Case when #groupBy = 'jobCode' then jobCode End
Thank you J0e3gan and mhasan for your efforts.

SQL Server (2005) Query Help

My query is based on the following example
I have table say 'Table1'. Table1 has one row and one column. The name of the column is 'Column1'. 'Column1' is a text column (NVARCHAR). I have a comma separated keywords like 'key1,key2..keyn'. I want to search these keywords individually in the column1.
So in the where clause the query should be something like
SELECT ... FROM Table1
WHERE Column1 LIKE '%key1%'
AND Column1 LIKE '%key2%'
AND Column1 LIKE '%keyn%'
I just want to know how to write a query in a simplified manner. Table is quite small and performance is not a main concern.
Just declare the keywords in a variable for the test case
DECLARE #Keywords NVARCHAR(MAX)
SET #Keywords = 'Key1,Key2,Key3'
A simple example will be helpful to me.
This will be easier if you get these into table format. (Split Table Valued functions exist to do this to your delimited string - e.g. http://www.eggheadcafe.com/community/aspnet/13/10021854/fnsplit.aspx)
DECLARE #Keywords TABLE
(
COL NVARCHAR(100)
)
INSERT INTO #Keywords SELECT 'Key1' UNION ALL SELECT 'Key2' UNION ALL SELECT 'Key3'
SELECT ...
FROM Table1 c
JOIN #Keywords k ON c.Column1 LIKE '%' + k.COL + '%'
GROUP BY ...
HAVING COUNT(*) = (select COUNT(*) FROM #Keywords)

Resources