I have a custom table where it shows custom_field as a column and display_value in another column.
I'm pulling hiring managers from there and some jobs have more than one hiring manager, so it results in multiple rows. I am trying to concatenate them into one row per job:
select
j.name,
string_agg(jcf.display_value, ' ,') as hiring_managers
from
jobs j
left join
job_custom_fields jcf on j.id = jcf.job_id
where
jcf.custom_field = 'Manager'
I'm using Postico as my SQL server client, but it's saying there isn't a function called string_agg available. I'm working within Amazon Redshift, so AFAIK I haven't had any issues with postgresql functions being implemented.
anyone have any ideas?
Related
I am new to SQL and DB management. I am working on writing queries based on a schema which you can find below. This is an exercise for me to get familiar reading, writing queries on SQL Server for my job. Could you please help me out defining query based on the schema and simply explain the logic?
Thanks a lot!
SQL Server is my DBMS and here are the question
Display ID, First Name, Last Name, and Hits to display all players with more than 2000 career hits.
This one you can get by typing this query in Microsoft SQL Server
SELECT
MLB_PLAYERS.FIRST_NAME,
MLB_PLAYERS.LAST_NAME,
MLB_PLAYERS.ID,
CAREER_STATS.HITS
FROM
MLB_PLAYERS LEFT JOIN KEY_GAMES_STATS on MLB_PLAYERS.ID=CAREER_STATS.ID
WHERE
CAREER_STATS.HITS>2000
So you have a simple structure to follow:
SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
But you decide to get only 3 of them, which is select, from and where. By SELECT you decide which columns you wanna have as an output. Then in FROM you have to choose tables from which you wanna take your variables. But if you decide to use 2 different tables you need to join them. I used left join because I wanted to match hits to existing players. We can match them by similar key, in this case this is their ID. And eventually, you can use where to apply conditions to your queries
I guess you could do it with a join and a group
select p.MLB_PLAYERS.FIRST_NAME,
p.MLB_PLAYERS.LAST_NAME,
p.MLB_PLAYERS.ID,
count(g.KEY_GAMES_STATS.HITS) as hits
from MLB_PLAYERS p
left join KEY_GAMES_STATS on p.ID = g.ID -- not sure how to link there 2 tables
group by p.MLB_PLAYERS.FIRST_NAME,
p.MLB_PLAYERS.LAST_NAME,
p.MLB_PLAYERS.ID
having count(g.KEY_GAMES_STATS.HITS) > 2000
This may have been mentioned here before, but I couldn't find an answer to the exact problem I'm trying to solve.
I am using SSMS 2018 v18.8 with SQL Server 2012 SP4.
My query requires querying multiple tables with joins.
One table (table 2) contains multiple values, and I'd like to return them in the query as a concatenated line.
How should I write my query to return the desired output?
Normally, you want the client application or reporting tool to roll up data like this. However, in Sql Server 2017 and later you can use the string_agg() function (along with GROUP BY) to make this happen.
SELECT t1.System, t1.Location, string_agg(t2.User, ',') As [User]
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.System=t2.System
GROUP BY t1.System, t1.Location
Earlier versions need an ugly FOR XML PATH query.
Very simple answer using US States and Counties, Counties table contains a key (StateID) identifying the State the County belongs to.
SELECT States.name, STRING_AGG(CONVERT(NVARCHAR(max), ISNULL(County,'N/A')), ', ') AS Counties
FROM Counties
join States on Counties.StateID=State.ID
GROUP BY States.name;
Important update:
When I try to use the suggested string_agg method I get this error - Specified types
or functions (one per INFO message) not supported on Redshift tables.
Original question
I have a query but I'm struggling to "pivot" multiple rows into a single column of strings.
I have a member and a category table and each member can have multiple categories (this is a simplification of the scenario).
So I need to write a query to display what categories each member has, so each member has multiple categories. When I was working in the Microsoft world I was able to use pivot but now in Postgres I'm not able to find an equivalent method.
I've seen references to crosstab and a few other methods but when trying I get errors saying the function isn't recognised.
My attempt!
select
m.member_id,
array.join(c.category, ",") -- this is more like a programming approach but I need something similar to this
from member m
from join category c ON c.member_id = m.id
group by 1
Example with dataset
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=8ea4998f75f7db83d2360ff01bf02c82
I'm using Navicat Premium as my "editor"
A second attempt
select b.member_id, string_agg(distinct c.name, ',')
from bookings b
join category c on c.member_id = b.member_id
group by 1
Redshift doesn't support string_agg() function but has the listagg() function which I believe is equivalent. See: https://docs.aws.amazon.com/redshift/latest/dg/r_LISTAGG.html
Listagg() support DISTINCT and even has a window function form. Does this not produce your desired results?
select b.member_id, listagg(distinct c.name, ',')
from bookings b
join category c on c.member_id = b.member_id
group by 1;
As for the error message in the update, that is Redshift's cryptic way to say that you have attempted to perform a leader node only operation on a compute node (or something of that ilk). I don't see why you would get that unless string_agg() is supported as a leader only operation (generate_series() is an example of a function only supported on the leader node).
I’ve built a few tables and queries in SQL Server, but now I’m stuck as to how to make them work together in this latest task.
There’s a table, we’ll called it ServerAssessment. It has an inventory of servers, such as their Name and their Server Edition, which is Developer, Production, Unknown, etc. There’s much larger table called DatabaseDetails that contains thousands of records regarding IDs. Each row has a Server Name, a User Name, and other details not needed here.
The difficulty I’m having is that I need to produce a query that lists only Developer servers (WHERE Server Edition = 'Developer') but also then follows up and lists every distinct User Name (from DatabaseDetails) following it.
From a SQL logic standpoint, I am not sure how this is best completed. It would look something like this, I would think? Or am I coming at this completely from the wrong angle?
ServerA001 User00001 User00002 User00003 User00111
ServerA015 User00001 User00002 User60005 User29031 User11111
ServerC037 User00001 User00009
ServerD066 User00001 User00002 User00003 User12312 User12333, User14141
ServerN123 User00001 User00003 User00009
Again, a user may have access to many, many servers. Should instead of listing everything out by distinct server, instead transpose everything so it's by distinct/unique User, and then list out the servers? Would one be more ideal in a professional atmosphere?
All I have currently is something short and sweet, to join the tables and make sure only Developer is returned.
SELECT
DISTINCT [Server Name]
, [Server Edition]
FROM [ServerAssessment] AS tabDI
FULL JOIN [DatabaseDetails] AS tabUD
ON tabDI.[Server Name] = tabUD.[Server Name]
WHERE [SQL Server Edition] = 'Developer'
ORDER BY [Computer Name] ASC
PS: These were originally tables in Excel, but I imported this into SQL Server since I feel more comfortable with SQL as of my work the last few months.
First, using a full join will give you records from details that are not directly related to developer servers. You want to use a left join instead to get all development servers but only details related to them.
Second you will have to look up how to do a dynamic sql pivot if you want to do this in SQL. This will cause trouble when creating a report as the number of columns will change. I suggest you use a reporting tool that can auto-pivot for you. I did something similar using SSRS/
I would use ROW_NUMBER function togheter with PIVOT operator thus:
SELECT *
FROM (
SELECT /*DISTINCT*/ tabDI.[ServerName], [UserName],
ColNum = ROW_NUMBER() OVER(PARTITION BY tabDI.[ServerName] ORDER BY [UserName])
FROM (VALUES
('ServerA001', 'Developer'),
('ServerA002', 'Enterprise'),
('ServerA015', 'Developer')
) AS tabDI ([ServerName], [SQL Server Edition]) -- [ServerAssessment]
LEFT JOIN (VALUES -- LEFT JOIN for servers without users
('ServerA001', 'User00001'),
('ServerA001', 'User00002'),
('ServerA001', 'User00003'),
('ServerA001', 'User00006'),
('ServerA002', 'User00001'),
('ServerA015', 'User00003'),
('ServerA015', 'User00004')
) AS tabUD ([ServerName], [UserName]) -- [DatabaseDetails]
ON tabDI.[ServerName] = tabUD.[ServerName]
WHERE [SQL Server Edition] = 'Developer'
) x
PIVOT ( MAX(x.UserName) FOR x.ColNum IN ([1], [2], [3], [4] /*, ...*/) ) y
ORDER BY y.[ServerName]
Note: This solution works for a limited number of users (4 in above case).
I have a query which gets all public transport subscriptions. A subscription can have multiple related companies. So I wanted to do with my query is to get all the subscriptions and instead of creating a row each time I have a related company, the companies should by group into one column. Is it possible to do that?
Here's the query :
SELECT pts.Id_PublicTransportSubscription,
pts.Amount,
ptc.Name
FROM bm_PublicTransportSubscriptions AS pts
INNER JOIN bm_PublicTransportSubscriptionByCompany AS ptsbc
ON pts.Id_PublicTransportSubscription = ptsbc.Id_PublicTransportSubscription
INNER JOIN bm_PublicTransportCompanies AS ptc
ON ptsbc.Id_PublicTransportCompany = ptc.Id_PublicTransportCompany
I'm using SQL Server 2008.
You can use the GROUP_CONCAT aggregate function.