Select statement from sql table - sql

Here is some QuestionID and OptionID with IsCorrect flag for every option, I am not getting a way to get the result set in the required format(shown in attached Image), it will be helpful if some one give some sort of suggestion with best way to achieve this, Thanks in Advance,
declare #temp table
(questionID int, optionID int, isCorrect bit, option_text varchar(50))
insert into #temp values
( 1, 1, 1, 'abc'), (1, 2, 1, 'pqr'), (1, 3, 0, 'mno' ),
(2, 1, 1, 'xyz' ), (2, 2, 1, 'def')

Try this:
SELECT T1.questionId
,option_text = SubString (( SELECT ', ' + T2.option_text
FROM #temp as T2
WHERE T1.questionId = T2.questionId
and isCorrect = 1
FOR XML PATH ( '' ) ), 3, 1000)
, 'key'as Answer
FROM #temp as T1
GROUP BY questionId
union all
select Questionid, Option_text, 'primary_key'
from #temp
order by 1
Create A Comma Delimited List From a Column

I think it's using GROUP_CONCAT function in SQL Server (2012?):
My answer is:
SQL Fiddle
SELECT
questionID AS [QuestionID]
, option_text AS [OptionText]
, CASE WHEN (CHARINDEX(',', option_text) > 0) THEN 'key'
WHEN (isCorrect = 1) THEN 'partial key'
ELSE 'wrong key' END AS [Answere]
FROM
(
SELECT questionID, option_text, isCorrect
FROM #temp
UNION ALL
SELECT
questionID
, LEFT(keys, LEN(keys) - 1)
, isCorrect
FROM
(
SELECT questionID
, (SELECT option_text + ','
FROM #temp
WHERE questionID = t.questionID AND isCorrect = 1
FOR XML PATH('')
) AS keys
, isCorrect
FROM #temp AS t
GROUP BY questionID, isCorrect
HAVING isCorrect = 1
) AS connected
) AS result
ORDER BY QuestionID, Answere

Related

Want to compare 4 different columns with the result of CTE

I have created a CTE (common table Expression) as follows:
DECLARE #N VARCHAR(100)
WITH CAT_NAM AS (
SELECT ID, NAME
FROM TABLE1
WHERE YEAR(DATE) = YEAR(GETDATE())
)
SELECT #N = STUFF((
SELECT ','''+ NAME+''''
FROM CAT_NAM
WHERE ID IN (20,23,25,30,37)
FOR XML PATH ('')
),1,1,'')
The result of above CTE is 'A','B','C','D','F'
Now I need to check 4 different columns CAT_NAM_1,CAT_NAM_2,CAT_NAM_3,CAT_NAM_4 in the result of CTE and form it as one column like follow:
Select
case when CAT_NAM_1 in (#N) then CAT_NAM_1
when CAT_NAM_2 in (#N) then CAT_NAM_2
when CAT_NAM_3 in (#N) then CAT_NAM_3
when CAT_NAM_4 in (#N) then CAT_NAM_4
end as CAT
from table2
When I'm trying to do the above getting error please help me to do.
If my approach is wrong help me with right one.
I am not exactly sure what you are trying to do, but if I understand the following script shows one possible technique. I have created some table variables to mimic the data you presented and then wrote a SELECT statement to do what I think you asked (but I am not sure).
DECLARE #TABLE1 AS TABLE (
ID INT NOT NULL,
[NAME] VARCHAR(10) NOT NULL,
[DATE] DATE NOT NULL
);
INSERT INTO #TABLE1(ID,[NAME],[DATE])
VALUES (20, 'A', '2021-01-01'), (23, 'B', '2021-02-01'),
(25, 'C', '2021-03-01'),(30, 'D', '2021-04-01'),
(37, 'E', '2021-05-01'),(40, 'F', '2021-06-01');
DECLARE #TABLE2 AS TABLE (
ID INT NOT NULL,
CAT_NAM_1 VARCHAR(10) NULL,
CAT_NAM_2 VARCHAR(10) NULL,
CAT_NAM_3 VARCHAR(10) NULL,
CAT_NAM_4 VARCHAR(10) NULL
);
INSERT INTO #TABLE2(ID,CAT_NAM_1,CAT_NAM_2,CAT_NAM_3,CAT_NAM_4)
VALUES (1,'A',NULL,NULL,NULL),(2,NULL,'B',NULL,NULL);
;WITH CAT_NAM AS (
SELECT ID, [NAME]
FROM #TABLE1
WHERE YEAR([DATE]) = YEAR(GETDATE())
AND ID IN (20,23,25,30,37,40)
)
SELECT CASE
WHEN EXISTS(SELECT 1 FROM CAT_NAM WHERE CAT_NAM.[NAME] = CAT_NAM_1) THEN CAT_NAM_1
WHEN EXISTS(SELECT 1 FROM CAT_NAM WHERE CAT_NAM.[NAME] = CAT_NAM_2) THEN CAT_NAM_2
WHEN EXISTS(SELECT 1 FROM CAT_NAM WHERE CAT_NAM.[NAME] = CAT_NAM_3) THEN CAT_NAM_3
WHEN EXISTS(SELECT 1 FROM CAT_NAM WHERE CAT_NAM.[NAME] = CAT_NAM_4) THEN CAT_NAM_4
ELSE '?' -- not sure what you want if there is no match
END AS CAT
FROM #TABLE2;
You can do a bit of set-based logic for this
SELECT
ct.NAME
FROM table2 t2
CROSS APPLY (
SELECT v.NAME
FROM (VALUES
(t2.CAT_NAM_1),
(t2.CAT_NAM_2),
(t2.CAT_NAM_3),
(t2.CAT_NAM_4)
) v(NAME)
INTERSECT
SELECT ct.NAM
FROM CAT_NAM ct
WHERE ct.ID IN (20,23,25,30,37)
) ct;

SQL - String concatenated grouping WITHOUT DISTINCT

I'm wondering if this is possible - I have a table like this:
pk int, num int, name varchar(1)
1 1 'a'
2 1 'b'
3 1 'c'
4 1 'd'
5 1 'e'
6 2 'f'
7 2 'g'
8 2 'h'
9 2 'i'
10 2 'j'
And I'd like an output like this WITHOUT using a DISTINCT clause:
num result
1 a,b,c,d,e
2 f,g,h,i,j
Here are ddl statements for testing:
declare #tbl table (pk int, num int, name varchar(1))
insert into #tbl select 1, 1, 'a'
insert into #tbl select 2, 1, 'b'
insert into #tbl select 3, 1, 'c'
insert into #tbl select 4, 1, 'd'
insert into #tbl select 5, 1, 'e'
insert into #tbl select 6, 2, 'f'
insert into #tbl select 7, 2, 'g'
insert into #tbl select 8, 2, 'h'
insert into #tbl select 9, 2, 'i'
insert into #tbl select 10, 2, 'j'
The following query works, but I'd like to eliminate the DISTINCT clause if possible:
select DISTINCT num, stuff((select ',' + name from #tbl where num = t.num for xml path('')), 1, 1, '')
from #tbl t
Any idea how to do this in SQL 2012+?
If you don't have a list of num values that you want, then you can create one. One rather silly way is:
select t.num,
stuff( (select ',' + name
from #tbl t2
where t2.num = t.num
for xml path('')
), 1, 1, '')
from (values (1), (2)) as t(num);
More commonly, this would be written as:
select t.num,
stuff( (select ',' + name
from #tbl t2
where t2.num = t.num
for xml path('')
), 1, 1, '')
from (select distinct num from #tbl) t;
Try this I think it will work fine
select num, group_concat(name) from table_name group by num;

Rows to single cell

I would like to get the desired output marked in green
the data points for each id get put into a single cell
Basically take all the events that have happened with A and attach it in the same order
Use Stuff Function:
DECLARE #tblTest AS Table(
ID INT,
EVENT VARCHAR(5)
)
INSERT INTO #tblTest VALUES
(1,'A'),
(1,'A'),
(1,'C'),
(2,'A'),
(2,'B'),
(2,'C')
SELECT DISTINCT
T1.ID,
STUFF
(
(SELECT '' + convert(varchar(10), T2.EVENT, 120)
FROM #tblTest T2
where T1.ID = T2.ID
FOR XML PATH (''))
, 1, 0, '') AS EVENT
FROM #tblTest T1
You can use FOR XML:
SELECT DISTINCT
ID,
(SELECT [EVENT] +''
FROM YourTable
WHERE ID = y.ID
FOR XML PATH('')
) as [EVENT]
FROM YourTable y
Output:
ID EVENT
1 AABCD
2 AABBCC
You can use UDF to do so as follows:
CREATE TABLE t(
id INT,
col CHAR(1)
);
INSERT INTO t VALUES (1,'a');
INSERT INTO t VALUES (1,'b');
INSERT INTO t VALUES (1,'c');
INSERT INTO t VALUES (1,'d');
INSERT INTO t VALUES (2,'e');
INSERT INTO t VALUES (2,'f');
INSERT INTO t VALUES (3,'g');
INSERT INTO t VALUES (4,'h');
The UDF (User defined function) -
USE [t]
GO
CREATE FUNCTION dbo.ConcatenateCols(#Id INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #RtnStr VARCHAR(MAX)
SELECT #RtnStr = COALESCE(#RtnStr + '','') + col
FROM dbo.t
WHERE id = #Id AND col > ''
RETURN #RtnStr
END
GO
Finally the query and result:
SELECT id, dbo.ConcatenateCols(id) AS Cols -- UDF - ConcatenateCols(id)
FROM t GROUP BY Id
CREATE TABLE #temp(Id INt,Event Nvarchar(25))
INSERT INTO #temp
SELECT 1,
'A'
UNION ALL
SELECT 1,
'A'
UNION ALL
SELECT 1,
'B'
UNION ALL
SELECT 1,
'C'
UNION ALL
SELECT 1,
'D'
UNION ALL
SELECT 2,
'A'
UNION ALL
SELECT 2,
'A'
UNION ALL
SELECT 2,
'B'
UNION ALL
SELECT 2,
'B'
UNION ALL
SELECT 2,
'C'
UNION ALL
SELECT 2,
'C'
SELECT DISTINCT ID,
(SELECT [EVENT] +''
FROM #temp
WHERE ID = y.ID
FOR XML PATH('') ) AS [EVENT]
FROM #temp y

SQL Cross Tab Function

Hi Dear All My friends,
I want to ask one thing about sql cross tab function.Currently, I am using sql 2008 express version and my table structure is like below.
UserID Str_Value
1 A
1 B
1 C
2 A
2 B
3 D
3 E
I want to get like this .
UserID Str_Value
1 A,B,C
2 A,B
3 D,E
I don't want to use cursor.Is there any function for that one?
Please give me the right way.I really appreciate it.
Thanks.
Best Regards,
Chong
Hope this helps. You can comment ORDER BY T1.Str_Value if not needed and set the nvarchar(500) size as required
SELECT DISTINCT T1.UserId,
Stuff(
(SELECT N', ' + T2.Str_Value
FROM t T2
WHERE T2.userId = T1.userid
ORDER BY T2.Str_Value
FOR XML PATH(''),TYPE).value('text()[1]','nvarchar(500)'),1,2,N'')
AS Str_Value
FROM t T1
SELECT UserId, LEFT(Str_Value, LEN(Str_Value) - 1) AS Str_Value
FROM YourTable AS extern
CROSS APPLY
(
SELECT Str_Value + ','
FROM YourTable AS intern
WHERE extern.UserId = intern.UserId
FOR XML PATH('')
) pre_trimmed (Str_Value)
GROUP BY UserId, Str_Value
Try this:
SELECT DISTINCT
t1.UserID,
Values = SUBSTRING((SELECT ( ', ' + t2.Str_Value)
FROM dbo.Users t2
ORDER BY
t2.Str_Value
FOR XML PATH( '' )
), 3, 4000 )FROM dbo.Users t1
GROUP BY t1.UserID
create table #temp
(
userid int,
str_value varchar(1)
)
insert into #temp values (1, 'A')
insert into #temp values (1, 'B')
insert into #temp values (1, 'C')
insert into #temp values (2, 'A')
insert into #temp values (2, 'B')
insert into #temp values (3, 'D')
insert into #temp values (3, 'E')
select userid, left(x.str_value, len(x.str_value) -1) as str_value
from #temp t
cross apply
(
select str_value + ','
FROM #temp t1
where t.userid = t1.userid
for xml path('')
) x (str_value)
group by userid, x.str_value
drop table #temp

SQL statement to select the value of the latest version of data based on the latest date

I have a simple query and am wondering if it could be more elegantly coded. The final solution has to be ansi-compliant.
I need to fetch the latest value from a table based on date and version. A sample would explain more clearly:
declare #t table (id int, due_date smalldatetime, version int, value nvarchar(10))
insert into #t select 3, '1/1/2010', 1, 'value 1'
insert into #t select 3, '1/1/2010', 2, 'value 2'
insert into #t select 3, '3/1/2010', 1, 'value 3'
insert into #t select 3, '3/1/2010', 2, 'value 4'
insert into #t select 3, '3/1/2010', 3, 'value 5'
insert into #t select 3, '3/1/2010', 4, 'value 6'
insert into #t select 3, '4/1/2010', 1, 'value 7'
insert into #t select 3, '4/1/2010', 2, 'value 8'
insert into #t select 3, '4/1/2010', 3, 'value 9'
select value from #t t
inner join (select due_date, version=max(version)
from #t where due_date = (select max(due_date) from #t) group by due_date) maxes
on t.due_date=maxes.due_date and t.version=maxes.version
So I would expect the output to be
value 9
which it is based on the above query.
I'm not particulary happy with this solution - any better ways to accomplish this?
You could use:
SELECT TOP 1
x.value
FROM #t x
ORDER BY x.due_date DESC, x.version DESC
TOP is not ANSI, though. Another option would be to use ANSI analytical/rank/windowing functions:
SELECT x.value
FROM (SELECT t.value,
ROW_NUMBER() OVER (ORDER BY t.due_date DESC, t.version DESC) AS rank
FROM #t t) x
WHERE x.rank = 1
But this requires a database that supports the functionality - MySQL doesn't, PostgreSQL only started in v8.4...
SELECT
value
FROM
#t T1
LEFT OUTER JOIN #t T2 ON
T2.id = T1.id AND
(
(T2.due_date > T1.due_date) OR
(T2.due_date = T1.due_date AND T2.version > T1.version)
)
WHERE
T2.id IS NULL
or...
SELECT
value
FROM
#t T1
WHERE
NOT EXISTS
(
SELECT
FROM
#t T2
WHERE
T2.id = T1.id AND
(
(T2.due_date > T1.due_date) OR
(T2.due_date = T1.due_date AND T2.version > T1.version)
)
)