I'm using Supabase and when a user calls endpoint /crypto_signals I want to do a SQL query first where I join notification table columns to crypto_signals based on crypto_signals id to notifications coin_id
crypto_signals table
id coin
1 BTC
2 ETH
3 SOL
notifications table
id id_coin user_id
1 1 1
2 3 2
Expected response when user 1 make request to /crypto_signal
id coin coin_id id_notification
1 BTC 1 1
2 ETH null null
3 SOL null null
Current code so far
select *
from crypto_signals
left join notifications
on crypto_signals.id = notifications.coin_id
Output
id coin coin_id user_id
3 ETH null null
4 BTC 1 1
null Sol null null
my crypto_signal id is lost and instead using the notifications id
EDIT SOLVED
select crypto_signals.*,
notifications.id as notification_id,
notifications.coin_id
from crypto_signals
left join notifications
on crypto_signals.id = notifications.coin_id
Related
I have two tables:
user
id
full_name
is_admin
is_active
1
Alan
0
1
2
Carl
0
1
3
Any
0
1
4
Jane
0
1
5
Marry
0
1
6
Pedri
0
1
7
admin
1
1
8
Mota
0
0
approver
id
subordinate_id
leader_id
main_leader_id
is_active
1
1
2
3
0
2
4
5
6
1
3
1
2
4
0
(subordinate_id, leader_id and main_leader_id are foreign keys that correspond to the id column of the user table)
I would like to perform a query that brings all user names that are not admin (user table is_admin=0) and that are active (user table is_active=1), and that if they have the id in the subordinate_id column in the approver table that only brings the name of that user that has the is_active of the approver table = 0.
That is, I would like to bring users that if they have any record as subordinate_id that only bring me those that are not active in the approver table.
I tried to get the data in the following way:
SELECT
full_name
FROM user AS U
LEFT JOIN approver AS A
ON U.id = A.subordinate_id
WHERE
A.id is null
AND
U.is_admin = 0
AND
U.is_active = 1
But with this query i only get the user name that not has a register in the approver table,
and in my case i want to get the user that have a register in the approver table as subordinate_id, but not if the register have the column 'is_active' equal to 1.
In my final result I could get something like this:
Alan
carl
any
marry
Pedri
In order to make this working, you should split the conditions in the WHERE clause into:
"user" conditions: is_admin = 0 AND is_active = 1
"approver" conditions: is not a subordinate OR is_active = 0
These two groups of conditions have to be set in AND.
SELECT DISTINCT user_.id, user_.full_name
FROM user_
LEFT JOIN approver
ON user_.id = approver.subordinate_id
WHERE (user_.is_admin = 0 AND user_.is_active = 1)
AND (approver.id IS NULL OR approver.is_active = 0)
Check the demo here.
Note: the DISTINCT keyword is necessary because the JOIN operation is made between two tables having cardinality 1:n.
I currently have the below results table:
Company ID
External ID
Attribute
Int Value
1
101
Calls
3
1
101
Emails
14
1
101
Accounts
4
2
102
Calls
2
2
102
Emails
17
2
102
Accounts
5
And I would like to transform my query results to show as below:
Company ID
External ID
Calls
Emails
Accounts
1
101
3
14
4
2
102
2
17
5
Is this possible and if so, how would I do this? I'm a new SQL user and can't seem to figure this out :)
This is my current query to get my results:
SELECT
ic.company_id,
ic.external_id,
icca.attribute,
icca.int_value
FROM
intercom_companies AS ic
LEFT JOIN intercom_companies_custom_attributes AS icca
ON ic.company_id = icca.company_id
A pivot query should work here:
SELECT
ic.company_id,
ic.external_id,
MAX(CASE WHEN icca.attribute = 'Calls'
THEN icca.int_value END) AS Calls,
MAX(CASE WHEN icca.attribute = 'Emails'
THEN icca.int_value END) AS Emails,
MAX(CASE WHEN icca.attribute = 'Accounts'
THEN icca.int_value END) AS Accounts
FROM intercom_companies AS ic
LEFT JOIN intercom_companies_custom_attributes AS icca
ON ic.company_id = icca.company_id
GROUP BY
ic.company_id,
ic.external_id;
I want to see how many messages are sent by users, so I have tables where I store the channel and another table where I store the authors and the actual data. An important part of this is that channels can be subchannels, meaning that they are children of another channel, but also have their own ID.
Table 1
Row ID
Guild ID
Channel ID
Parent Channel ID (foreign key on Table 1 Channel ID)
1
1
2
null
2
1
3
null
3
1
4
3
Table 2
Row ID
Parent Channel ID (foreign key on Table 1 Channel ID)
Author ID
Messages
1
2
1
6
2
3
2
54
3
4
1
3
I have a query that gets the sum of messages from Channel IDs that are not a child of any other channel ID:
SELECT sc."guild_id" guild, sc."channel_id" channel, sum(s."NUM") num
FROM statistic s
INNER JOIN statschannel sc on s.parent_channel_id = sc.channel_id
GROUP BY sc."guild_id", sc."channel_id";
I would like to change the query so that the SUM() of (GUILD ID 1, CHANNEL ID 3) includes the sum of (GUILD ID 1, CHANNEL ID 4), as channel with ID 4 is a child channel. I tried doing an inner join, show below, but it only returns the results for the channels with a parent ID.
SELECT sc."guild_id" guild, sc."channel_id" channel, sum(s."NUM") num
FROM statistic s
INNER JOIN statschannel sc on s.parent_channel_id = sc.channel_id
INNER JOIN statschannel sc2 on sc.parent_channel_id = sc2.channel_id
GROUP BY sc."guild_id", sc."channel_id";
I don't know what to do here. The data that I want returned should look like this:
Guild ID
Channel ID
Messages
1
2
6
1
3
57 ( 54 + 3)
1
4
3
I managed to make a solution that provided the results I wanted.
SELECT "statschannel"."guild_id" "guild_id",
"statschannel"."channel_id" "channel_id",
SUM("statistic2"."NUM") + COALESCE(SUM("statistic"."NUM"), 0) "num"
FROM "statschannel"
LEFT OUTER JOIN "statschannel" "statschannel__parent_channel"
ON "statschannel__parent_channel"."channel_id" =
"statschannel"."parent_channel_id"
LEFT OUTER JOIN "statistic" ON "statschannel__parent_channel"."channel_id" =
"statistic"."parent_channel_id"
LEFT OUTER JOIN "statistic" "statistic2" ON "statschannel".channel_id =
"statistic2".parent_channel_id
GROUP BY statschannel."guild_id", "statschannel"."channel_id"
This will provide the following results:
guild_id
channel_id
messages
1
2
6
1
3
57
1
4
3
I have a table with a source_id and destination_id and a message and I want to group messages together. There can only be one message between a given source_id and destination_id, but I only want rows that have a mutual response for a given ID (say id 1). In the following examples, I want rows #1, #2, #4 and #5 because there is a mutual response between id 1 and 2 and between id 1 and id 4 (id 1 sent a message to id 2 and id 2 sent a message to id 1, similarly, id 1 sent a message to id 4 and id 4 sent a message to id 1). I don't want id 3 because it has no mutual response.
How do I select this in SQL? (I'm using PostgreSQL btw)
Example:
table messages
# source_id destination_id message
1 1 2 hello
2 2 1 hi
3 1 3 bye
4 1 4 thanks
5 4 1 okay
6 3 5 blablabla
7 5 3 hooray
Preferably, I want my select to return these 4 rows:
1 1 2 hello
2 2 1 hi
3 1 4 thanks
4 4 1 okay
Thanks in advance :)
You seem to be describing exists:
select m.*
from messages m
where exists (select 1
from messages m2
where m2.source_id = m.destination_id and
m2.source_id = m.destination_id
);
In your example, this would also return rows 6 and 7, because those seem to follow the rule you specified.
If you want 1 to be one of the ids, then include a filter for that:
select m.*
from messages m
where 1 in (m.source_id, m.destination_id) and
exists (select 1
from messages m2
where m2.source_id = m.destination_id and
m2.source_id = m.destination_id
);
Do a self join:
select m1.*
from messages m1
join messages m2
on m1.source_id = m2.destination_id
and m2.source_id = m1.destination_id
where 1 in (m1.source_id, m2.source_id)
I have 2 tables named user and statistics
user table has 3 columns: id, name and category
statistics table has 3 columns: id, idUser (relational), cal
something like this:
user
Id name category
1 name1 1
2 name2 2
3 name3 3
statistics
Id idUser cal
1 1 1
2 1 1
3 1 1
4 2 1
5 2 1
How can I apply a query that sum the cal column by each category of users and give me something like this:
category totalcal
1 3
2 2
3 0
You want to do a left join to keep all the categories. The rest is just aggregation:
select u.category, coalesce(sum(s.cal), 0) as cal
from users u left join
statistics s
on u.id = s.idUser
group by u.category;
Use LEFT JOIN to get 0 sum for the category=3:
SELECT
user.category
,SUM(statistics.cal) AS totalcal
FROM
user
LEFT JOIN statistics ON statistics.idUser = user.Id
GROUP BY
user.category
Here SUM would return NULL for category=3. To get 0 instead of NULL you can use COALESCE(SUM(statistics.cal), 0).