Can we use Select query output as Column alias - tsql

i need a select statements output as a columns's alias
is it possible
examples
select columnname as (select value from tablename) from tablename
output
values
1
2
3

no you can't, see this:
declare #a table (rowvalue varchar(20))
insert #a values ('aaa')
insert #a values ('bbb')
insert #a values ('ccc')
insert #a values ('ddd')
declare #x table (id int,rowvalue varchar(20))
insert #x values (1, 'wowwee')
insert #x values (2, 'noooo!')
select a.rowvalue as (select rowvalue from #x where id=1)
from #a a
OUTPUT:
Msg 102, Level 15, State 1, Line 11
Incorrect syntax near '('.
Msg 156, Level 15, State 1, Line 12
Incorrect syntax near the keyword 'from'.
you'll have to use dynamic sql for this.
EDIT to show dynamic sql:
declare #SQL varchar(500)
,#ColumnName varchar(20)
create table #a (rowvalue varchar(20))
insert #a values ('aaa')
insert #a values ('bbb')
insert #a values ('ccc')
insert #a values ('ddd')
declare #x table (id int,rowvalue varchar(20))
insert #x values (1, 'wowwee')
insert #x values (2, 'noooo!')
SELECT #ColumnName=rowvalue FROM #x where id=1
set #SQL='select a.rowvalue as '+#ColumnName+' from #a a'
exec(#SQL)
OUTPUT:
wowwee
--------------------
aaa
bbb
ccc
ddd
(4 row(s) affected)

Try this
Select (Select value from Tablename) as Columnname from Tablename
The output should resemble the following
ColumnName
- 1
- 2
- 3

I think you have to quit de AS word in tsql, I mean:
select column name (select value from tablename) from tablename

Related

pivot or reshapre sql [duplicate]

I've been tasked with coming up with a means of translating the following data:
date category amount
1/1/2012 ABC 1000.00
2/1/2012 DEF 500.00
2/1/2012 GHI 800.00
2/10/2012 DEF 700.00
3/1/2012 ABC 1100.00
into the following:
date ABC DEF GHI
1/1/2012 1000.00
2/1/2012 500.00
2/1/2012 800.00
2/10/2012 700.00
3/1/2012 1100.00
The blank spots can be NULLs or blanks, either is fine, and the categories would need to be dynamic. Another possible caveat to this is that we'll be running the query in a limited capacity, which means temp tables are out. I've tried to research and have landed on PIVOT but as I've never used that before I really don't understand it, despite my best efforts to figure it out. Can anyone point me in the right direction?
Dynamic SQL PIVOT:
create table temp
(
date datetime,
category varchar(3),
amount money
)
insert into temp values ('1/1/2012', 'ABC', 1000.00)
insert into temp values ('2/1/2012', 'DEF', 500.00)
insert into temp values ('2/1/2012', 'GHI', 800.00)
insert into temp values ('2/10/2012', 'DEF', 700.00)
insert into temp values ('3/1/2012', 'ABC', 1100.00)
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.category)
FROM temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT date, ' + #cols + ' from
(
select date
, amount
, category
from temp
) x
pivot
(
max(amount)
for category in (' + #cols + ')
) p '
execute(#query)
drop table temp
Results:
Date ABC DEF GHI
2012-01-01 00:00:00.000 1000.00 NULL NULL
2012-02-01 00:00:00.000 NULL 500.00 800.00
2012-02-10 00:00:00.000 NULL 700.00 NULL
2012-03-01 00:00:00.000 1100.00 NULL NULL
Dynamic SQL PIVOT
Different approach for creating columns string
create table #temp
(
date datetime,
category varchar(3),
amount money
)
insert into #temp values ('1/1/2012', 'ABC', 1000.00)
insert into #temp values ('2/1/2012', 'DEF', 500.00)
insert into #temp values ('2/1/2012', 'GHI', 800.00)
insert into #temp values ('2/10/2012', 'DEF', 700.00)
insert into #temp values ('3/1/2012', 'ABC', 1100.00)
DECLARE #cols AS NVARCHAR(MAX)='';
DECLARE #query AS NVARCHAR(MAX)='';
SELECT #cols = #cols + QUOTENAME(category) + ',' FROM (select distinct category from #temp ) as tmp
select #cols = substring(#cols, 0, len(#cols)) --trim "," at end
set #query =
'SELECT * from
(
select date, amount, category from #temp
) src
pivot
(
max(amount) for category in (' + #cols + ')
) piv'
execute(#query)
drop table #temp
Result
date ABC DEF GHI
2012-01-01 00:00:00.000 1000.00 NULL NULL
2012-02-01 00:00:00.000 NULL 500.00 800.00
2012-02-10 00:00:00.000 NULL 700.00 NULL
2012-03-01 00:00:00.000 1100.00 NULL NULL
I know this question is older but I was looking thru the answers and thought that I might be able to expand on the "dynamic" portion of the problem and possibly help someone out.
First and foremost I built this solution to solve a problem a couple of coworkers were having with inconstant and large data sets needing to be pivoted quickly.
This solution requires the creation of a stored procedure so if that is out of the question for your needs please stop reading now.
This procedure is going to take in the key variables of a pivot statement to dynamically create pivot statements for varying tables, column names and aggregates. The Static column is used as the group by / identity column for the pivot(this can be stripped out of the code if not necessary but is pretty common in pivot statements and was necessary to solve the original issue), the pivot column is where the end resultant column names will be generated from, and the value column is what the aggregate will be applied to. The Table parameter is the name of the table including the schema (schema.tablename) this portion of the code could use some love because it is not as clean as I would like it to be. It worked for me because my usage was not publicly facing and sql injection was not a concern. The Aggregate parameter will accept any standard sql aggregate 'AVG', 'SUM', 'MAX' etc. The code also defaults to MAX as an aggregate this is not necessary but the audience this was originally built for did not understand pivots and were typically using max as an aggregate.
Lets start with the code to create the stored procedure. This code should work in all versions of SSMS 2005 and above but I have not tested it in 2005 or 2016 but I can not see why it would not work.
create PROCEDURE [dbo].[USP_DYNAMIC_PIVOT]
(
#STATIC_COLUMN VARCHAR(255),
#PIVOT_COLUMN VARCHAR(255),
#VALUE_COLUMN VARCHAR(255),
#TABLE VARCHAR(255),
#AGGREGATE VARCHAR(20) = null
)
AS
BEGIN
SET NOCOUNT ON;
declare #AVAIABLE_TO_PIVOT NVARCHAR(MAX),
#SQLSTRING NVARCHAR(MAX),
#PIVOT_SQL_STRING NVARCHAR(MAX),
#TEMPVARCOLUMNS NVARCHAR(MAX),
#TABLESQL NVARCHAR(MAX)
if isnull(#AGGREGATE,'') = ''
begin
SET #AGGREGATE = 'MAX'
end
SET #PIVOT_SQL_STRING = 'SELECT top 1 STUFF((SELECT distinct '', '' + CAST(''[''+CONVERT(VARCHAR,'+ #PIVOT_COLUMN+')+'']'' AS VARCHAR(50)) [text()]
FROM '+#TABLE+'
WHERE ISNULL('+#PIVOT_COLUMN+','''') <> ''''
FOR XML PATH(''''), TYPE)
.value(''.'',''NVARCHAR(MAX)''),1,2,'' '') as PIVOT_VALUES
from '+#TABLE+' ma
ORDER BY ' + #PIVOT_COLUMN + ''
declare #TAB AS TABLE(COL NVARCHAR(MAX) )
INSERT INTO #TAB EXEC SP_EXECUTESQL #PIVOT_SQL_STRING, #AVAIABLE_TO_PIVOT
SET #AVAIABLE_TO_PIVOT = (SELECT * FROM #TAB)
SET #TEMPVARCOLUMNS = (SELECT replace(#AVAIABLE_TO_PIVOT,',',' nvarchar(255) null,') + ' nvarchar(255) null')
SET #SQLSTRING = 'DECLARE #RETURN_TABLE TABLE ('+#STATIC_COLUMN+' NVARCHAR(255) NULL,'+#TEMPVARCOLUMNS+')
INSERT INTO #RETURN_TABLE('+#STATIC_COLUMN+','+#AVAIABLE_TO_PIVOT+')
select * from (
SELECT ' + #STATIC_COLUMN + ' , ' + #PIVOT_COLUMN + ', ' + #VALUE_COLUMN + ' FROM '+#TABLE+' ) a
PIVOT
(
'+#AGGREGATE+'('+#VALUE_COLUMN+')
FOR '+#PIVOT_COLUMN+' IN ('+#AVAIABLE_TO_PIVOT+')
) piv
SELECT * FROM #RETURN_TABLE'
EXEC SP_EXECUTESQL #SQLSTRING
END
Next we will get our data ready for the example. I have taken the data example from the accepted answer with the addition of a couple of data elements to use in this proof of concept to show the varied outputs of the aggregate change.
create table temp
(
date datetime,
category varchar(3),
amount money
)
insert into temp values ('1/1/2012', 'ABC', 1000.00)
insert into temp values ('1/1/2012', 'ABC', 2000.00) -- added
insert into temp values ('2/1/2012', 'DEF', 500.00)
insert into temp values ('2/1/2012', 'DEF', 1500.00) -- added
insert into temp values ('2/1/2012', 'GHI', 800.00)
insert into temp values ('2/10/2012', 'DEF', 700.00)
insert into temp values ('2/10/2012', 'DEF', 800.00) -- addded
insert into temp values ('3/1/2012', 'ABC', 1100.00)
The following examples show the varied execution statements showing the varied aggregates as a simple example. I did not opt to change the static, pivot, and value columns to keep the example simple. You should be able to just copy and paste the code to start messing with it yourself
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','sum'
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','max'
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','avg'
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','min'
This execution returns the following data sets respectively.
Updated version for SQL Server 2017 using STRING_AGG function to construct the pivot column list:
create table temp
(
date datetime,
category varchar(3),
amount money
);
insert into temp values ('20120101', 'ABC', 1000.00);
insert into temp values ('20120201', 'DEF', 500.00);
insert into temp values ('20120201', 'GHI', 800.00);
insert into temp values ('20120210', 'DEF', 700.00);
insert into temp values ('20120301', 'ABC', 1100.00);
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = (SELECT STRING_AGG(category,',') FROM (SELECT DISTINCT category FROM temp WHERE category IS NOT NULL)t);
set #query = 'SELECT date, ' + #cols + ' from
(
select date
, amount
, category
from temp
) x
pivot
(
max(amount)
for category in (' + #cols + ')
) p ';
execute(#query);
drop table temp;
There's my solution cleaning up the unnecesary null values
DECLARE #cols AS NVARCHAR(MAX),
#maxcols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(CodigoFormaPago)
from PO_FormasPago
order by CodigoFormaPago
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #maxcols = STUFF((SELECT ',MAX(' + QUOTENAME(CodigoFormaPago) + ') as ' + QUOTENAME(CodigoFormaPago)
from PO_FormasPago
order by CodigoFormaPago
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT CodigoProducto, DenominacionProducto, ' + #maxcols + '
FROM
(
SELECT
CodigoProducto, DenominacionProducto,
' + #cols + ' from
(
SELECT
p.CodigoProducto as CodigoProducto,
p.DenominacionProducto as DenominacionProducto,
fpp.CantidadCuotas as CantidadCuotas,
fpp.IdFormaPago as IdFormaPago,
fp.CodigoFormaPago as CodigoFormaPago
FROM
PR_Producto p
LEFT JOIN PR_FormasPagoProducto fpp
ON fpp.IdProducto = p.IdProducto
LEFT JOIN PO_FormasPago fp
ON fpp.IdFormaPago = fp.IdFormaPago
) xp
pivot
(
MAX(CantidadCuotas)
for CodigoFormaPago in (' + #cols + ')
) p
) xx
GROUP BY CodigoProducto, DenominacionProducto'
t #query;
execute(#query);
The below code provides the results which replaces NULL to zero in the output.
Table creation and data insertion:
create table test_table
(
date nvarchar(10),
category char(3),
amount money
)
insert into test_table values ('1/1/2012','ABC',1000.00)
insert into test_table values ('2/1/2012','DEF',500.00)
insert into test_table values ('2/1/2012','GHI',800.00)
insert into test_table values ('2/10/2012','DEF',700.00)
insert into test_table values ('3/1/2012','ABC',1100.00)
Query to generate the exact results which also replaces NULL with zeros:
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX),
#PivotColumnNames AS NVARCHAR(MAX),
#PivotSelectColumnNames AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT #PivotColumnNames= ISNULL(#PivotColumnNames + ',','')
+ QUOTENAME(category)
FROM (SELECT DISTINCT category FROM test_table) AS cat
--Get distinct values of the PIVOT Column with isnull
SELECT #PivotSelectColumnNames
= ISNULL(#PivotSelectColumnNames + ',','')
+ 'ISNULL(' + QUOTENAME(category) + ', 0) AS '
+ QUOTENAME(category)
FROM (SELECT DISTINCT category FROM test_table) AS cat
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery =
N'SELECT date, ' + #PivotSelectColumnNames + '
FROM test_table
pivot(sum(amount) for category in (' + #PivotColumnNames + ')) as pvt';
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery
OUTPUT :
A version of Taryn's answer with performance improvements:
Data
CREATE TABLE dbo.Temp
(
[date] datetime NOT NULL,
category nchar(3) NOT NULL,
amount money NOT NULL,
INDEX [CX dbo.Temp date] CLUSTERED ([date]),
INDEX [IX dbo.Temp category] NONCLUSTERED (category)
);
INSERT dbo.Temp
([date], category, amount)
VALUES
({D '2012-01-01'}, N'ABC', $1000.00),
({D '2012-01-02'}, N'DEF', $500.00),
({D '2012-01-02'}, N'GHI', $800.00),
({D '2012-02-10'}, N'DEF', $700.00),
({D '2012-03-01'}, N'ABC', $1100.00);
Dynamic pivot
DECLARE
#Delimiter nvarchar(4000) = N',',
#DelimiterLength bigint,
#Columns nvarchar(max),
#Query nvarchar(max);
SET #DelimiterLength = LEN(REPLACE(#Delimiter, SPACE(1), N'#'));
-- Before SQL Server 2017
SET #Columns =
STUFF
(
(
SELECT
[text()] = #Delimiter,
[text()] = QUOTENAME(T.category)
FROM dbo.Temp AS T
WHERE T.category IS NOT NULL
GROUP BY T.category
ORDER BY T.category
FOR XML PATH (''), TYPE
)
.value(N'text()[1]', N'nvarchar(max)'),
1, #DelimiterLength, SPACE(0)
);
-- Alternative for SQL Server 2017+ and database compatibility level 110+
SELECT #Columns =
STRING_AGG(CONVERT(nvarchar(max), QUOTENAME(T.category)), N',')
WITHIN GROUP (ORDER BY T.category)
FROM
(
SELECT T2.category
FROM dbo.Temp AS T2
WHERE T2.category IS NOT NULL
GROUP BY T2.category
) AS T;
IF #Columns IS NOT NULL
BEGIN
SET #Query =
N'SELECT [date], ' +
#Columns +
N'
FROM
(
SELECT [date], amount, category
FROM dbo.Temp
) AS S
PIVOT
(
MAX(amount)
FOR category IN (' +
#Columns +
N')
) AS P;';
EXECUTE sys.sp_executesql #Query;
END;
Execution plans
Results
date
ABC
DEF
GHI
2012-01-01 00:00:00.000
1000.00
NULL
NULL
2012-01-02 00:00:00.000
NULL
500.00
800.00
2012-02-10 00:00:00.000
NULL
700.00
NULL
2012-03-01 00:00:00.000
1100.00
NULL
NULL
CREATE TABLE #PivotExample(
[ID] [nvarchar](50) NULL,
[Description] [nvarchar](50) NULL,
[ClientId] [smallint] NOT NULL,
)
GO
INSERT #PivotExample ([ID],[Description], [ClientId]) VALUES ('ACI1','ACI1Desc1',1008)
INSERT #PivotExample ([ID],[Description], [ClientId]) VALUES ('ACI1','ACI1Desc2',2000)
INSERT #PivotExample ([ID],[Description], [ClientId]) VALUES ('ACI1','ACI1Desc3',3000)
INSERT #PivotExample ([ID],[Description], [ClientId]) VALUES ('ACI1','ACI1Desc4',4000)
INSERT #PivotExample ([ID],[Description], [ClientId]) VALUES ('ACI2','ACI2Desc1',5000)
INSERT #PivotExample ([ID],[Description], [ClientId]) VALUES ('ACI2','ACI2Desc2',6000)
INSERT #PivotExample ([ID],[Description], [ClientId]) VALUES ('ACI2','ACI2Desc3', 7000)
SELECT * FROM #PivotExample
--Declare necessary variables
DECLARE #SQLQuery AS NVARCHAR(MAX)
DECLARE #PivotColumns AS NVARCHAR(MAX)
--Get unique values of pivot column
SELECT #PivotColumns= COALESCE(#PivotColumns + ',','') + QUOTENAME([Description])
FROM (SELECT DISTINCT [Description] FROM [dbo].#PivotExample) AS PivotExample
--SELECT #PivotColumns
--Create the dynamic query with all the values for
--pivot column at runtime
SET #SQLQuery =
N' -- Your pivoted result comes here
SELECT ID, ' + #PivotColumns + '
FROM
(
-- Source table should in a inner query
SELECT ID,[Description],[ClientId]
FROM #PivotExample
)AS P
PIVOT
(
-- Select the values from derived table P
SUM(ClientId)
FOR [Description] IN (' + #PivotColumns + ')
)AS PVTTable'
--SELECT #SQLQuery
--Execute dynamic query
EXEC sp_executesql #SQLQuery
Drop table #PivotExample
Fully generic way that will work in non-traditional MS SQL environments (e.g. Azure Synapse Analytics Serverless SQL Pools) - it's in a SPROC but no need to use as such...
-- DROP PROCEDURE IF EXISTS
if object_id('dbo.usp_generic_pivot') is not null
DROP PROCEDURE dbo.usp_generic_pivot
GO;
CREATE PROCEDURE dbo.usp_generic_pivot (
#source NVARCHAR (100), -- table or view object name
#pivotCol NVARCHAR (100), -- the column to pivot
#pivotAggCol NVARCHAR (100), -- the column with the values for the pivot
#pivotAggFunc NVARCHAR (20), -- the aggregate function to apply to those values
#leadCols NVARCHAR (100) -- comma seprated list of other columns to keep and order by
)
AS
BEGIN
DECLARE #pivotedColumns NVARCHAR(MAX)
DECLARE #tsql NVARCHAR(MAX)
SET #tsql = CONCAT('SELECT #pivotedColumns = STRING_AGG(qname, '','') FROM (SELECT DISTINCT QUOTENAME(', #pivotCol,') AS qname FROM ',#source, ') AS qnames')
EXEC sp_executesql #tsql, N'#pivotedColumns nvarchar(max) out', #pivotedColumns out
SET #tsql = CONCAT ( 'SELECT ', #leadCols, ',', #pivotedColumns,' FROM ',' ( SELECT ',#leadCols,',',
#pivotAggCol,',', #pivotCol, ' FROM ', #source, ') as t ',
' PIVOT (', #pivotAggFunc, '(', #pivotAggCol, ')',' FOR ', #pivotCol,
' IN (', #pivotedColumns,')) as pvt ',' ORDER BY ', #leadCols)
EXEC (#tsql)
END
GO;
-- TEST EXAMPLE
EXEC dbo.usp_generic_pivot
#source = '[your_db].[dbo].[form_answers]',
#pivotCol = 'question',
#pivotAggCol = 'answer',
#pivotAggFunc = 'MAX',
#leadCols = 'candidate_id, candidate_name'
GO;

How Coalesce works in sql server?

Create table test(Names varchar(100) primary key )
insert into test values('Hugeman')
insert into test values('Jack')
insert into test values('William')
insert into test values('Kevin')
insert into test values('Peter')
Query 1:
declare #sql varchar(100)
select #sql = coalesce(#sql+'+','')+Names from test order by names-- where object_id =object_id('temp')
print #sql
This will result as
Hugeman+Jack+Kevin+Peter+William
Query 2
declare #sql varchar(100)
select #sql = coalesce(Names+'+','') from test order by names-- where object_id =object_id('temp')
print #sql
This will results William+
As per the documentation of coalesce, will return the first not null value. So it has to result Hugeman+. But it returns the entire rows.
Why query2 haven't done the same ?
This is not stricly connected to COALESCE.
Try these SELECTs:
DECLARE #sql1 AS VARCHAR(1000)
SELECT #sql1 = ISNULL(#sql1, '') + Names FROM test ORDER BY Names
PRINT #sql1
DECLARE #sql2 AS VARCHAR(1000)
SELECT #sql2 = Names FROM test ORDER BY Names
PRINT #sql2
So what happened? For EACH record selected:
in query 1 you keep adding values to #sql
in query 2 you reset #sql as the last name extracted
I don't understand exactly what you want to obtain from your SELECT, but a better example of COALESCE could be:
CREATE TABLE TEST2(Name VARCHAR(100) PRIMARY KEY, Telephone VARCHAR(10), Mobile VARCHAR(10))
INSERT INTO TEST2 VALUES('Hugeman', 1, 2)
INSERT INTO TEST2 VALUES('Jack', NULL, 3)
INSERT INTO TEST2 VALUES('William', 4, NULL)
INSERT INTO TEST2 VALUES('Kevin', 5, 6)
INSERT INTO TEST2 VALUES('Peter', NULL, NULL)
SELECT Name,
COALESCE(Telephone, Mobile) AS Tel
FROM TEST2
#sql is on the right hand side on the first to get appended
On the last #sql is all alone on the left side and has the value of the last row
Query-1: Appending the values of all rows to #sql
Query-2: Re-setting values to #sql
The below is the rows with order by names
Hugeman
Jack
Kevin
Peter
William
Query-1 Appends all values to #sql.
Query-2 Re-writing values to #sql, so the last row in the list is William so when you print the variable the last re-assigned value is printed.
The COALESCE() function returns the first non null value from the from the columns as parameters in COALESCE() function.
e.g.
SELECTCOALESCE(null,null,1,2) ///return --1
SELECT Id, COALESCE(FirstName, MiddleName, LastName) AS Name
FROM tblEmployee //return 1st non null value from FirstName/MiddleName/LastName

where exists - all - group by?

I use SQL Server 2008 R2.
I have a weird problem as following. I have a table as shown in
I need to write such a query like:
SELECT DISTINCT Field1
FROM MYTABLE
WHERE Field2 IN (96,102)
in this query, WHERE Field2 IN (96,102) gives me 96 or 102 or both!
More over, I would like to return rows that contains 96 and 102 at the same time!
Is there any suggestion? please write result oriented...
I have made a sqlfiddle for this..
create table a (id int, val int)
go
insert into a select 1, 22
insert into a select 1, 122
insert into a select 2, 22
insert into a select 3, 122
insert into a select 4, 22
insert into a select 4, 122
then select like this
select count(distinct id), id
from a
where val in (22, 122)
group by id
having count(id) > 1
EDIT: count(distinct id) will only show distinct counts..
EDIT:
Here's a sqlfiddle example (thanks to Mark Kremers):
http://sqlfiddle.com/#!3/df201/1
create table mytable (field1 int, field2 int)
go
insert into mytable values (199201, 84)
insert into mytable values (199201, 96)
insert into mytable values (199201, 102)
insert into mytable values (199201, 103)
insert into mytable values (581424, 96)
insert into mytable values (581424, 84)
insert into mytable values (581424, 106)
insert into mytable values (581424, 122)
insert into mytable values (687368, 79)
insert into mytable values (687368, 96)
insert into mytable values (687368, 102)
insert into mytable values (687368, 104)
insert into mytable values (687368, 106)
Here's the query:
select distinct a.field1 from
( select field1 from mytable where field2=96) a
inner join
( select field1 from mytable where field2=102) b
on a.field1 = b.field1
And here are the results:
FIELD1
199201
687368
Finally, here's a simplified version of the query (thans to pst):
select distinct a.field1 from mytable a
inner join mytable b
on a.field1 = b.field1
where a.field2=96 and b.field2=102
Use a self-join? Not the most tidy, but I think it works well for 2 values
SELECT *
FROM T R1
JOIN T R2 -- join table with itself
ON R1.F1 = R2.F1 -- where the first field is the same
WHERE R1.F2 = 96 AND R2.F2 = 102 -- and each has one of the required values
(T = Table, Rx = Relation Alias, Fx = Field)
If there can be an arbitrary number of fields, this can be solved as
CREATE TABLE #T (id int, val int)
GO
INSERT INTO #T (id, val)
VALUES
(1, 22), (1, 22), -- no, only 22 (but 2 records)
(2, 22), (2, 122), -- yes, both values (only)
(3, 122), -- no, only 122
(4, 22), (4,122), -- yes, both values ..
(4, 444), (4, null), -- and extra values
(5, 555) -- no, neither value
GO
-- Using DISTINCT over filtered results first, as
-- SQL Server 2008 does not support HAVING COUNT(DISTINCT F1, F2)
SELECT id
FROM (SELECT DISTINCT id, val
FROM #T
WHERE val IN (22, 122)) AS R1
GROUP BY id
HAVING COUNT(id) >= 2 -- or 3 or ..
GO
-- Or a similar variation, as can COUNT(DISTINCT ..)
-- in the SELECT of a GROUP BY
SELECT id
FROM (SELECT id, COUNT(DISTINCT val) as ct
FROM #T
WHERE val IN (22, 122)
GROUP BY id) AS R1
WHERE ct >= 2 -- or 3 or ..
GO
For larger IN (..) sizes, say above 20 values, it may be advisable to use a separate table or table-value and a JOIN for performance reasons.
Try from your original query:
SELECT DISTINCT Field1
FROM MYTABLE
WHERE rtrim(ltrim(cast(Field2 as varchar))) IN ('96','102')

insert into table with ID column

I am attempting to insert columns from a temp table and want the ID column to increment sequentially. I'm using the following code but nothing is getting inserted:
INSERT INTO TestDataTable
SELECT Code, Description, ParentID FROM TempTable
Kindly tell me how I can get this to work.
You need to make the ID an IDENTITY column. So in your select into statement, something like this should do:
INSERT INTO TestDataTable
SELECT ID = IDENTITY(INT,1,1), Code, Description, ParentID FROM TempTable
I would say that you have two options. The first is to handle this in the data definition language of your target table. See this code example written for MS SQL Server.
CREATE TABLE #A (
Id INT NOT NULL IDENTITY(1,1) PRIMARY KEY
, Code VARCHAR(10) NOT NULL)
CREATE TABLE #B (
Code VARCHAR(10) NOT NULL)
INSERT INTO #B VALUES ('alpha')
INSERT INTO #B VALUES ('beta')
INSERT INTO #B VALUES ('gamma')
INSERT INTO #B VALUES ('delta')
INSERT INTO #A (Code)
SELECT Code
FROM #B
SELECT *
FROM #A
DROP TABLE #A
DROP TABLE #B
If you are not allowed to handle in the target table's DDL then you can accomplish what you need be specifying on the way into the table like this if you know it will be empty.
CREATE TABLE #A (
Id INT NOT NULL PRIMARY KEY
, Code VARCHAR(10) NOT NULL)
CREATE TABLE #B (
Code VARCHAR(10) NOT NULL)
INSERT INTO #B VALUES ('alpha')
INSERT INTO #B VALUES ('beta')
INSERT INTO #B VALUES ('gamma')
INSERT INTO #B VALUES ('delta')
INSERT INTO #A (Id, Code)
SELECT ROW_NUMBER() OVER (ORDER BY Code), Code
FROM #B
SELECT *
FROM #A
DROP TABLE #A
DROP TABLE #B
I definitely recommend the first method. It is much simpler and you don't have to worry about handling the auto-increment in code.

Would this be an appropriate situations for a cursor?

I have the following script:
SELECT left(SHI.FSOKEY, 6) AS [SoNo]
, substring(SHI.FSOKEY, 7, 3) AS [So Item]
, right(SHI.FSOKEY, 3) AS [So Rels]
, QAL.FCLOT AS [LotSerial]
FROM shmast SHM
INNER JOIN shitem SHI
ON SHM.FSHIPNO = SHI.FSHIPNO
INNER JOIN qalotc QAL
ON SHM.FSHIPNO = Left(QAL.FCUSEINDOC, 6)
AND substring(QAL.FCUSEINDOC, 7, 6) = SHI.FITEMNO
This produces output that looks like this:
SoNo So Item SoRels LotSerial
123456 1 001 ABCD
123456 1 001 AMOH
123456 1 001 POWK
123456 1 001 IUIL
123456 1 002 ABCE
I want to group by SoNo, SoItem, SoRels and get a list of LotSerials for each. So, my output would look like this:
SoNo So Item SoRels LotSerial
123456 1 001 ABCD, AMOH, POWK, IUIL
123456 1 002 ABCE
I need to do so that I can pull this information back into a main query based on the SoNo, SoItem, SoRels.
Any help would be greatly appreciated.
As always, avoid cursors whenever possible. Your scenario would be a good fit for a user defined function. I simplified your schema a little for this example. Essentially we are concatenating the serials that match with commas to a variable within a user defined function, and then retuning the result. If Null values are possible, you might want to add usage of Coalesce
create table SO (SONO int)
insert into SO values (1)
insert into SO values (2)
insert into SO values (3)
create table SOCHILD
(SONO int, SerialNo varchar(10))
insert into SOCHILD values (1, 'ABCD')
insert into SOCHILD values (1, 'EFGH')
insert into SOCHILD values (1, 'IJKL')
GO
create function fx_GetSerials(#SONO int)
returns varchar(1000) as
Begin
Declare #ret varchar(1000)
set #ret = ''
Select #ret = #ret + SerialNo + ','
from SOCHILD where SONO = #SONO
if (len(#ret) > 0)
set #Ret = left(#ret, len(#ret) -1)
return #ret
End
GO
select dbo.Fx_GetSerials(1)
drop function fx_GetSerials
Drop table SO
Drop table SOCHILD
Results
ABCD,EFGH,IJKL
#cmsjr beat me to it with his answer which is just bout the same. I do build the string differently, and have a complete working example.
try this:
CREATE TABLE YourTable (SoNo int, SoItem int, SoRels char(3), LotSerial char(4))
go
INSERT INTO YourTable VALUES (123456,1,'001','ABCD')
INSERT INTO YourTable VALUES (123456,1,'001','AMOH')
INSERT INTO YourTable VALUES (123456,1,'001','POWK')
INSERT INTO YourTable VALUES (123456,1,'001','IUIL')
INSERT INTO YourTable VALUES (123456,1,'002','ABCE')
go
CREATE FUNCTION LotSerial_to_CVS(#SoNo int, #SoItem int, #SoRels char(3))
RETURNS varchar(2000) AS
BEGIN
DECLARE #cvs varchar(2000)
SELECT #cvs=ISNULL(#cvs+', ','')+LotSerial
FROM YourTable
WHERE SoNo=#SoNo AND SoItem=#SoItem AND SoRels=#SoRels
RETURN #cvs
END
go
SELECT
SoNo, SoItem, SoRels, dbo.LotSerial_to_CVS(SoNo, SoItem, SoRels)
FROM YourTable
GROUP BY SoNo, SoItem, SoRels
OUTPUT:
SoNo SoItem SoRels
----------- ----------- ------ -----------------------
123456 1 001 ABCD, AMOH, POWK, IUIL
123456 1 002 ABCE
(2 row(s) affected)
There is no need for a cursor in almost ANY case any more.
You can do the same thing using XML PATH as well. Here is a working sample:
SET NOCOUNT ON
Declare #MyTable Table
(
SoNo VarChar (100),
SoItem VarChar (100),
SoRels VarChar (100),
LotSerial VarChar (100)
)
INSERT INTO #MyTable Values ('123456', '1', '001', 'ABCD')
INSERT INTO #MyTable Values ('123456', '1', '001', 'AMOH')
INSERT INTO #MyTable Values ('123456', '1', '001', 'POWK')
INSERT INTO #MyTable Values ('123456', '1', '001', 'IUIL')
INSERT INTO #MyTable Values ('123456', '1', '002', 'ABCE')
SELECT
SoNo,
SoItem,
SoRels,
STUFF ((
SELECT ', ' + LotSerial
FROM #MyTable T1
WHERE 1=1
AND T1.SoNo = T2.SoNo
AND T1.SoItem = T2.SoItem
And T1.SoRels = T2.SoRels
FOR XML PATH ('')
), 1, 2, '') AS LotSerial
FROM #MyTable T2
GROUP BY SoNo, SoItem, SoRels