Group by on table, list all of one attribute for each of another attribute [duplicate] - sql

This question already has an answer here:
Is there any function in oracle similar to group_concat in mysql? [duplicate]
(1 answer)
Closed 9 years ago.
I'm attempting to group this data by name so that instead of current query output giving me:
Name Number
Nice guy 1
Nice guy 2
Nice guy 4
Nice guy 5
Nice guy 6
Nice guy 7
Nice guy 8
Nice guy 9
Nice guy 10
Nice guy 11
Nice guy 12
Frank 3
Frank 4
I would get this:
Name Number
Nice guy 1,2,4,...
Frank 3,4
Here is my current query:
select distinct name, number
from patterns,numbers,people
where patterns.index=numbers.index
AND patterns.id=people.id
order by name, charge;
What I have tried is this, but it fails:
select distinct name, number
from patterns,numbers,people
where patterns.index=numbers.index
AND patterns.id=people.id
group by name
order by name, number;
Any help would be greatly appreciated!

UPDATED: Try it this way
SELECT name, WM_CONCAT(number) number
FROM
(
SELECT DISTINCT name, number
FROM patterns t JOIN numbers n
ON t.index = n.index JOIN people p
ON t.id = p.id
) q
GROUP BY name
ORDER BY name

Related

PostgreSQL check parent of parent in query

Okay, I'll try to be as precise as possible. I have a database with comments who have a parent_comment_id. I want to select a number of comments from this table and a matching number of answers to these comments. Here comes my problem: If I arbitrarily select comments, I might grab some who don't have any answers. However, if I select comment answers first, I might grab answers who are an answer to another comment already. So, what I want to do is grab answers who are immediate answers to a comment (parent_comment_id = NULL) and then get those comments base on the parent_comment_id. How would I go about this in a query?
Assume this layout of a database
comment_id parent_comment_id
1 NULL
2 NULL
3 1
4 3
5 1
6 3
7 1
8 4
9 NULL
10 NULL
...
Now, I would select, let's say 2 answers and the corresponding comments. If I just select the first 2 answers, I would get comment 3 and 4, but if I backtrace those, I would only get comment 1, because comment 4 is an answer to an answer. Instead, I would want to find only comments whose parent comment has no parent comment, which would be comment 3 and 5 in this example.
I haven't really tried anything beyound realizing it doesn't work without somehow recursively getting parents which I have no clue how to do in SQL queries.
I solved it with a pretty easy solution. Might be horrible practice, but works for my use-case ^^
For the given example it would be something like this:
select distinct on (parent_comment_id) c.id, c.parent_comment_id, c.text
from comments c
where parent_comment_id is not null
and (select parent_comment_id from comments p where id = c.parent_comment_id) is null
I would want to find only comments whose parent comment has no parent comment.
I think that you just want a self-join and some filtering:
select c.*
from comments c
inner join comments pc on pc.comment_id = c.parent_comment_id
where pc.parent_comment_id is null
You could also use exists:
select c.*
from comments c
where exists (
select 1
from comments pc
where pc.comment_id = c.parent_comment_id and pc.parent_comment_id is null
)

Concatenate many rows into comma-separated list based on unique id [duplicate]

This question already has answers here:
Simulating group_concat MySQL function in Microsoft SQL Server 2005?
(12 answers)
Closed 8 years ago.
I'm new to SQL (running SQL Server 2012), the query I'm running is returning these results.
IDNum Email
----------------
1 a#a.com
1 b#b.com
1 c#c.com
2 d#d.com
2 e#e.com
3 f#f.com
3 g#g.com
3 h#h.com
4 i#i.com
5 j#j.com
5 k#k.com
I would like to get the following result set (a comma separated list unique to each id)
IDNum Emails
---------------------------------
1 a#a.com,b#b.com,c#c.com
2 d#d.com,e#e.com
3 f#f.com,g#g.com,h#h.com
4 i#i.com
5 j#j.com,k#k.com
I've been trying to follow some of the answers from other questions but not having any luck. I'm sure it's some combination of my inexperience & all the other questions I'm finding with this are just results from a single table. My query is getting results from multiple tables if that makes a difference, would be similar to
SELECT DISTINCT
s.idnum, e.email
FROM
student s
JOIN
email e ON e.guid = s.guid
WHERE
s.activeYear = 1 AND e.activeEmail = 1
Can anyone help? Thanks.
******UPDATE******
I ended up using the following query after reading a few more articles here and on another website. Hope this helps someone in the future.
USE databaseName
SELECT s.idnum,
STUFF(( SELECT ',' + e.email AS [text()]
FROM email e
WHERE
e.guid = s.guid AND e.activeEmail = 1
FOR XML PATH('')
), 1, 1, '' )
AS emails
FROM student s
WHERE s.activeYear = 1
In Oracle you would do this with a LISTAGG function, but for SQL-Server try this question, there's a few different options there:
ListAGG in SQLSERVER

Counting totals and partials

I have a table answers in a PostgreSQL engine powered database, with a number associated to a question. I need to count how many numbers are there and how many of them are below 6 grouped by question.
What I want is something like:
SELECT question, count(*) AS Qanswers, count_below_6(*) AS Qanswers_below_6
FROM answers
GROUP BY question;
question | Qanswers | Qanswers_below_6
-----------------------+----------+------------------
How do you feel? | 1234 | 53
Was clear the webinar? | 8444 | 20
How much that hurt? | 3666 | 142
Currently I'm doing
SELECT question, count(*) AS Qanswers
FROM answers
GROUP BY question;
And then
SELECT question, count(*) AS Qanswers
FROM answers
WHERE value < 6
GROUP BY question;
After that I merge the two results manually.
Can I make a single sentence that gives me the result as I need?
SELECT question
,count(*) AS answers
,count(value < 6 OR NULL) AS under_6
FROM answers
GROUP BY question;
The trick is that count(expression) only counts non-null values (while count(*) counts all rows). Here is a detailed explanation why we get NULL in the right places:
Compute percents from SUM() in the same SELECT sql query
There is a number of equivalent techniques to achieve that. Detailed comparison with a benchmark:
For absolute performance, is SUM faster or COUNT?

Random selection of rows from sql result set? [duplicate]

This question already has answers here:
How to request a random row in SQL?
(30 answers)
Closed 9 years ago.
i have a query which will result 10 or 20 or any number number of rows. Below is the query.
select bookname from bookstore where recommend='true' and Year(pubdate)='2013'
This query can give me any number of rows.
But i have to show just 4 rows from the result. I can select top 4 but i would like select randomly so that every time same book name is not shown through out the year for the users when they visit.
Please help me how to get random rows from the result.
SELECT TOP 4 bookname
FROM bookstore
WHERE recommend = 'true' AND
Year(pubdate)='2013'
ORDER BY NEWID()
select
bookname
from
bookstore
where
recommend='true' and
Year(pubdate)='2013'
order by
rand()
limit 4
Edit: For slq-server use newid() instead of rand()

How do I average numbers according to each distinct ID in SQL?

I have CommentRating table that holds a foreign key to the DrinkId. I'm trying to get the average ratings for each DrinkId, and along with that I want to display the top three drinkIds that have the highest ratings.
commentRating drinkID
9 7
9 4
8 11
8 7
7 4
6 4
6 11
Here's the SQL I have so far, but I don't know how to change it.
Select TOP(3)(AVG(commentRating)),DISTINCT(drinkID)
FROM Comment order by commentRating desc
How do I average the ratings, select the drinks with the top three ratings, and return them in SQL?
You need to GROUP BY the result by the drinkID:
SELECT TOP 3 AVG(commentRating), drinkID
FROM Comment
GROUP BY drinkID
ORDER BY AVG(commentRating) DESC
I recommend you to read your favorite SQL documentation about details on GROUP BY. For T-SQL it is GROUP BY (Transact-SQL) on MSDN.
AVG is an aggregate function. Again, I'd recommend you to read some documentation on aggregate functions, in T-SQL it's in the MSDN library too.
For T-SQL:
select TOP 3 * from
(
select drinkID,avg(commentRating) avgCom
from Comment group by drinkID
) t order by avgCom DESC
For MySQL use LIMIT key word.