the IN clause does not works in my embedded SQL statement - sql-server

I have following Table
Table User
UserID Name
1 Om
2 John
3 Kisan
4 Lisa
5 Karel
Table Game
Games Players
Golf 1,3,5
Football 4
I wrote query:
Select UserId,
Name from User
Where UserID IN
(Select Players from Game where Games='Golf')
Result:
~~~~~~~
0 Rows
Above query does not return me any result while it works well when i directly specify values for In clause in statement.
Select UserId, Name
from User
Where UserID IN (1,3,5)
Result:
~~~~~~~
UserID Name
1 Om
3 Kisan
5 Karel
3 rows
However when I change the condition in very 1st query with Football:
Select UserId, Name
from User
Where UserID IN
(Select Players
from Game
where Games='Football').
This returns me following result:
UserID Name
4 Lisa
1 row
How I can work around so that my very 1st query returns me the right result?
I think I'm in wrong direction. Help me out!

This is what you get for storing comma separated values in a field. Now you have to split it, using, say this function and do something like
Select User.UserId, User.Name from User
inner join splitstring((Select Players from Game where Games='Golf')) a
on User.UserID = a.Name
But consider changing your table "Game" design to
Games Players
Golf 1
Golf 3
Golf 5
Football 4
Then you can do simple
Select User.UserId, User.Name
from User inner join Game
on User.UserID = Game.Players
Where Game.Games = 'Golf'
without any additional functions.

Your first query translates to this:
Select UserId, Name
from User
Where UserID IN (`1,3,5`)
Notice that it is a string representation of the IDs, not a comma separated list like in your second query.
There are many Split functions out there written for this very scenario.
You can utilize one of them as such:
DECLARE #PlayersCsv NVARCHAR(MAX)
Select #PlayersCsv = Players from Game where Games='Golf'
Select UserId,
Name from User
Where UserID IN
(Select Value FROM dbo.Split(#PlayersCsv, ','))

DECLARE #xml AS xml
SET #xml = (SELECT cast('<X>'+(''+replace(players,',' ,'</X><X>')+'</X>') AS xml)
FROM Game WHERE Games='Golf')
SELECT UserId, Name
FROM User
WHERE UserID IN
(SELECT N.value('.', 'varchar(10)') as value FROM #xml.nodes('X') as T(N))
SQL Fiddle Results:
| USERID | NAME |
|--------|-------|
| 1 | Om |
| 3 | Kisan |
| 5 | Karel |

Related

Laravel DB custom

I have 2 tables like this
Table tname Table tfriend
id name id nameid friendid
1 rick 1 1 2
2 roy 2 1 3
3 richard 3 2 1
4 3 1
and I want output like this
id name friends
1 rick roy, richard
2 roy rick
3 richard rick
I already make this query db like this :
$friend = \DB::select('SELECT id, name, (SELECT friendid as friends from tfriends WHERE nameid = id) FROM tname')->get()
but that select inside select is not worked even in SQL query is work, what should I write in query to make it right ?
You can try it:
select(id, name, (select tname.name from tfriend,tname where (select tfriend.id from tfriend,tname where tname.id = tfriend.nameid) = tname.id) as friends)
you need to have the id in a variable and concat into query, if is integer you can use simple concatenation style without dots and without quotation marks around the variable, ex>
$query = DB::select(" SELECT * (SELECT friendid as friends from tfriends WHERE nameid = $id) FROM tname");
var_dump($query);
well I have a little tricky for my solution that I use in this
first, I do declare 2 of my Db using join table tfriend with tname and declare regularly for table tname then I sent it to my blade
second, I do if-else in my blade like this
#foreach ($names $name)
{{$name->id}}
{{$name->name}}
#foreach ($friends as $friend)
#if ($friend->nameid == $name->id)
{{$friend->name}}<br>
#endif
#endforeach
#endforeach

Sql Server Weird CASE Statement

I am attempting to do something, but I am not sure if it is possible. I don't really know how to look up something like this, so I'm asking a question here.
Say this is my table:
Name | Group
-----+--------
John | Alpha
Dave | Alpha
Dave | Bravo
Alex | Bravo
I want to do something like this:
SELECT TOP 1 CASE
WHEN Group = 'Alpha' THEN 1
WHEN Group = 'Bravo' THEN 2
WHEN Group = 'Alpha' AND
Group = 'Bravo' THEN 3
ELSE 0
END AS Rank
FROM table
WHERE Name = 'Dave'
I understand why this won't work, but this was the best way that I could explain what I am trying to do. Basically, I just need to know when one person is a part of both groups. Does anyone have any ideas that I could use?
You should create a column to hold the values you want to sum and sum them, probably easiest to do this via a subquery:
Select Name, SUM(Val) as Rank
FROM (SELECT Name, CASE WHEN Group = 'Alpha' THEN 1
WHEN Group = 'Bravo' THEN 2
ELSE 0 END AS Val
FROM table
WHERE Name = 'Dave') T
GROUP BY Name
You can add TOP 1 and ORDER BY SUM(Val) to get the top ranked row if required.
After reading your comment, it could be simplified further to:
Select Name, COUNT([GROUP]) GroupCount
FROM table
GROUP BY Name
HAVING COUNT([GROUP]) > 1
That will simply return all names where they have more than 1 group.

SQL Server 2016 filter inside json_value

I have a feeds table with a json array column (UserLike) of people who like it. Table will be like:
FeedID FeedName UserLike
1 Feed 1 [{"UserID":1,"UserName":"User 1"},{"UserID":2,"UserName":"User 2"},...]
2 Feed 2 [{"UserID":1,"UserName":"User 1"},{"UserID":2,"UserName":"User 2"},...]
3 Feed 3 [{"UserID":1,"UserName":"User 1"}]
I want to get list of feeds and exactly like info of user login by compare UserID (if he has liked, or not return UserLike null, i want to get feed row even if login user is not in UserLike list).
How can I do it? Does T-SQL support some thing like:
select
FeedID, FeedName,
Json_value(UserLike, '$[UserID=1].UserName')...
The result that i'm expecting is:
FeedID FeedName UserID UserName
1 Feed 1 2 User 2
2 Feed 2 2 User 2
3 Feed 3 NULL NULL
with WHERE clause: UserID=2
--Here we take all feeds
;WITH cte AS (
SELECT DISTINCT FeedID,
FeedName
FROM dbo.feeds
--Here we take parsed JSON
), feeds AS (
SELECT FeedID,
FeedName,
UserID,
UserName
FROM [dbo].[feeds] f
CROSS APPLY OPENJSON ([UserLike])
WITH (
UserID int,
UserName nvarchar(255)
))
--And here we join them
SELECT c.FeedID,
c.FeedName,
f.UserID,
f.UserName
FROM cte c
LEFT JOIN feeds f
ON f.FeedID = c.FeedID and f.UserID = 2
Output:
FeedID FeedName UserID UserName
1 Feed 1 2 User 2
2 Feed 2 2 User 2
3 Feed 3 NULL NULL

Max Value with unique values in more than one column

I feel like I'm missing something really obvious here.
Using T-SQL/SQL-Server:
I have unique values in more than one column but want to select the max version based on one particular column.
Dataset:
Example
ID | Name| Version | Code
------------------------
1 | Car | 3 | NULL
1 | Car | 2 | 1000
1 | Car | 1 | 2000
Target status: I want my query to only select the row with the highest version value. Running a MAX on the version column pulls all three because of the distinct values in the 'Code' column:
SELECT ID
,Name
,MAX(Version)
,Code
FROM Table
GROUP BY ID, Name, Code
The net result is that I get all three entries as per the data set due to the unique values in the Code column, but I only want the top row (Version 3).
Any help would be appreciated.
You need to identify the row with the highest version as 1 query and use another outer query to pull out all the fields for that row. Like so:
SELECT t.ID, t.Name, GRP.Version, t.Code
FROM (
SELECT ID
,Name
,MAX(Version) as Version
FROM Table
GROUP BY ID, Name
) GRP
INNER JOIN Table t on GRP.ID = t.ID and GRP.Name = t.Name and GRP.Version = t.Version
You can also use row_number() to do this kind of logic, for example like this:
select ID, Name, Version, Code
from (
select *, row_number() over (order by Version desc) as RN
from Table1
) X where RN = 1
Example in SQL Fiddle
add the top statment to force the return of a single row. Also add the order by notation
SELECT top 1 ID
,Name
,MAX(Version)
,Code
FROM Table
GROUP BY ID, Name, Code
order by max(version) desc

How can I add an integer from another table to the current selected table in SQL Server?

Does anyone know how can I add an integer from another table to the current selected table in SQL Server?
For example:
I have 2 tables with the following information in each table
tableA:
id username point status country
1 alvin 1 1 U.S.A
2 alvin 1 1 U.S.A
3 amy 1 0 Australia
tableB:
id username point
1 amy 1
2 alvin 1
3 ken 1
How can I sum up the total points in tableA with also add in the sum points from tableB?
I tried the following code, but seem is not working and error display:
SELECT username, (COUNT(distinct a.point) + (SELECT SUM(a.point)
FROM tableB b WHERE b.username = a.username) AS 'Points', status, country
FROM tableA
GROUP BY aco.username
And the output I expected will be:
username Points status country
alvin 3 1 U.S.A
amy 2 0 Australia
WITH Results(username,point)
AS
(
SELECT username, point FROM TableA
UNION ALL
SELECT username, point FROM TableB
)
SELECT username, sum(point) AS Points FROM Results GROUP BY username
GO
EDIT
The question has changed, so now the solution should look like this
WITH Results(username,point,status, country)
AS
(
SELECT username, point, status, country FROM TableA
UNION ALL
SELECT username, point, null, null FROM TableB
)
SELECT username, sum(point) AS Points, max(status), max(country) FROM Results GROUP BY username
GO
What is WITH ?
What is UNION ?
You don't mention why Ken doesn't appear in the output table, I assume that TableA is the 'master' list. If so I would do the following INNER JOIN which is the most simple solution.
SELECT a.username AS Username, SUM(ISNULL(a.point,0)+ISNULL(b.point,0)) as Points,
MAX(a.Status) as Status, MAX(a.Country) as Country
FROM TableA a
INNER JOIN TableB b
ON a.username=b.username
GROUP BY a.username

Resources