Laravel DB custom - database

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

Related

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.

Count each unique content

How do I count how many times the content of a field nameappears in my table?
Name | Other
Brad | smth
Brad | smth
Daniel | smth
Matt | smth
Matt | smth
Matt | smth
For example,for the above table I would like to know how many times I have 'Brad',how many times 'Daniel' and how many times 'Matt'.How do I do this with just one select?
I'm interested in this because I want do display only the Names that appear more times than a given value.
My actual code:
select director.LastName,director.FirstName,count(director.FirstName)as counter,film.title
from director,film
where film.Id_Director=director.id
group by director.LastName,director.FirstName,film.title
having count(Director.FirstName)>2
Baz Luhrmann 1 Paranormal activity 4
Baz Luhrmann 1 Struck by lightning
Baz Luhrmann 1 The big bang theory
Baz Luhrmann 1 The family
Baz Luhrmann 1 The Quarterback
Brad Falchuk 1 A Kitty or a Gaga
Brad Falchuk 1 All or nothing
Brad Falchuk 1 Bridesmaids
Brian Dan 1 All or nothing
I was expecting it to count exactly how many times 'Baz' appears in the table(this should be done for every name) and display only if the value of count > the 3 for example.
Group by the name and use a count()
select name, count(*) as name_count
from your_table
group by name
Aggregate functions like count are applied for each group.
To display only names that appear more than 1 time you can do
select name, count(*) as name_count
from your_table
group by name
having count(*) > 1
Having is like a where clause but for groups.
Edit
select d.LastName, d.FirstName, count(f.Id_Director) as counter
from director d
inner join film f on f.Id_Director = d.id
group by d.LastName, d.FirstName
having count(f.Id_Director) > 2
You had grouped by the film too. That won't work. You basically queried for directors that are more than 2 times part of a film.
The problem is you are grouping by film. Since there are a director/film is ill away count as 1.
You you want to keep the film names in that select result set I suggest you make a select movies and a subquery to count how many times that director can be joined to other movies.
Just writed a example at SQLFiddle
Example

the IN clause does not works in my embedded SQL statement

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 |

MSSQL join tables w bit

I have three tables :
1) UserTable
UserId UserName
1 Mike
2 John
3 Jennifer
2) FormName
fID fName
1 edit
2 cafe
3 backoffice
3)User to form
fId UserId Allowed(bit)
1 1 0
2 1 1
3 1 1
2 2 1
3 2 0
The first table is the user table with user informations.
The second table is the form table where it stores form names of application
The third table is user level table where it says which user is allowed to open which form .
I want to create sql query where I can see all information in a single table like :
UserId USerName Edit Cafe BackOffice
1 mike 0 1 1
2 john 1 1 0
I think it is possbile with SQL Fiddle and Pivot but I am having hard time to figure the right code out .
You can use the PIVOT function, but you have to cast the allowed column to something other than a bit datatype. For example, the below casts it to an int:
select userid, username,
coalesce(Edit, 0) Edit,
coalesce(Cafe, 0) Cafe,
coalesce(BackOffice, 0) BackOffice
from
(
select u.userid,
u.username,
f.fname,
cast(allowed as int) allowed
from usertable u
inner join user_form uf
on u.userid = uf.userid
inner join formname f
on uf.fid = f.fid
) d
pivot
(
max(allowed)
for fname in (Edit, Cafe, BackOffice)
) piv;
See SQL Fiddle with Demo

TSQL: Get all rows for given ID

I am trying to output all of my database reports into one report. I'm currently using nested select statements to get each line for each ID (the number of ID's is unknown). Now I would like to return all the rows for every ID (e.g. 1-25 if there are 25 rows) in one query. How would I do this?
SELECT (
(SELECT ... FROM ... WHERE id = x) As Col1
(SELECT ... FROM ... WHERE id = x) As Col2
(SELECT ... FROM ... WHERE id = x) As Col3
)
EDIT: Here's an example:
SELECT
(select post_id from posts where report_id = 1) As ID,
(select isnull(rank, 0) from results where report_id = 1 and url like '%www.testsite.com%') As Main,
(select isnull(rank, 0) from results where report_id = 1 and url like '%.testsite%' and url not like '%www.testsite%') As Sub
This will return the rank of a result for the main domain and the sub-domain, as well as the ID for the posts table.
ID Main Sub
--------------------------------------
1 5 0
I'd like to loop through this query and change report_id to 2, then 3, then 4 and carry on until all results are displayed. Nothing else needs to change other than the report_id.
Here's a basic example of what is inside the tables
POSTS
post_id post report_id
---------------------------------------------------------
1 "Hello, I am..." 1
2 "This may take..." 2
3 "Bla..." 2
4 "Bla..." 3
5 "Bla..." 4
RESULTS
result_id url title report_id
--------------------------------------------------------
1 http://... "Intro" 1
2 http://... "Hello!" 1
3 http://... "Question" 2
4 http://... "Help" 3
REPORTS
report_id description
---------------------------------
1 Introductions
2 Q&A
3 Starting Questions
4 Beginner Guides
5 Lectures
The query will want to pull the first post, the first result from the main website (www) and the first result from a subdomain by their report_id. These tables are part of a complicated join structure with many other tables but for these purposes these tables are the only ones that are needed.
I've managed to solve the problem by creating a table, setting variables to take all the contents and insert them in a while loop, then selecting them and dropping the table. I'll leave this open for a bit to see if anyone picks up a better way of doing it because I hate doing it this way.
If you need each report id on its own column, take a look at the PIVOT/UNPIVOT commands.
Here's one way of doing it :
SELECT posts.post_id AS ID,
IsNull(tblMain.Rank, 0) AS Main,
IsNull(tblSub.Rank, 0) AS Sub
FROM posts
LEFT JOIN results AS tblMain ON posts.post_id = tblMain.report_id AND tblMain.url like '%www.testsite.com%'
LEFT JOIN results AS tblSub ON posts.post_id = tblSub.report_id AND tblSub.url like '%.testsite%' and tblSub.url not like '%www.testsite%'
That is one query? You've provided your own answer?
If you mean you want to return a series of 'rows' as, for some reason, 'columns', this ability does exist, but I can't remember the exact name. Possible pivot. But it's a little odd.
see if this is what you are looking
SELECT
CASE WHEN reports.id = 1 THEN reports.Name
ELSE "" AS Col1,
CASE WHEN reports.id = 2 THEN reports.Name
ELSE "" AS Col2
....
FROM reports
Best Regards,
Iordan
Assuming you have a "master" table of IDs (if not I suggest you do so for Foreign Key purposes):
SELECT (
(SELECT ... FROM ... WHERE id = m.ID) As Col1
(SELECT ... FROM ... WHERE id = m.ID) As Col2
(SELECT ... FROM ... WHERE id = m.ID) As Col3
)
FROM MasterIDs m
Depending on how much each report is similar,you may be able to speed that up by moving some of the logic out of the nested statements and into the main body of the query.
Possibly a better way of thinking about this is to alter each report statement to return (ID,value) and do something like:
SELECT
report1.Id
,report1.Value AS Col1
,report2.Value AS Col2
FROM (SELECT Id, ... AS Value FROM ...) report1
JOIN (SELECT Id, ... AS Value FROM ...) report2 ON report1.Id = report2.Id
again, depending on the similarity of your reports you could probably combine these in someway.

Resources