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
Related
I have a table
id
repeat customer id
store
date
1
A
07-19-22
2
A
07-19-22
3
A
07-19-22
id
repeat customer id
store
date
1
B
07-19-22
2
B
07-19-22
3
1
B
07-19-22
4
B
07-19-22
and more tables from other store
The problem here is
all stores start with id 1
repeat customer have new id in id column and their original id is retained in repeat customer id column
I have to concatenated all the tables and also keep track of repeating customer for analytics. I have joined all tables using UNION ALL and also created a dummy id column using SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS NEW_ID, * FROM CTE, but I have no clue how to capture and assign value to repeat customer id such that I get the table as below
NEW_ID
id
new_repeat_customer_id
repeat customer id
store
date
1
1
A
07-19-22
2
2
A
07-19-22
3
3
A
07-19-22
4
1
B
07-19-22
5
2
B
07-19-22
6
3
4
1
B
07-19-22
7
4
B
07-19-22
The best way to incorporate it, would be to use Alphanumeric String as NEW_ID, and concat STORE and ID to create NEW_ID. For example A_000000001. In that way you can add similar STORE to REPEAT_CUSTOMER_ID as well.
So in this case, instead of NEW_ID=6, you would have NEW_ID=B_000000003 and REPEAT_CUSTOMER_ID would become B_000000001.
But in case that is not possible, you can use query like below to get the output
DB Fiddle Query
with CTE as
(
select * from STORE1
UNION ALL
select * from STORE2
)
,CTE2 as
(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS NEW_ID,t.* from CTE t)
,REPEAT_ID as
(select NEW_ID,ID,REPEAT_CUSTOMER_ID,STORE from CTE2 where REPEAT_CUSTOMER_ID is not null)
,REPEACT_CUSTOMER_ID as
(select c.NEW_ID as NEW_REPEAT_CUSTOMER_ID,r.NEW_ID
from REPEAT_ID r
left join CTE2 c
on c.ID=r.REPEAT_CUSTOMER_ID and c.STORE=r.STORE
)
select c.* , n.NEW_REPEAT_CUSTOMER_ID
from CTE2 c
left join REPEACT_CUSTOMER_ID n
on c.NEW_ID=n.NEW_ID
https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=cbe63994b10f9e3b0eff53b0c89d463a
SO basically you have to separate rows where REPEATE customer is present and join it with main table query.
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
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 am trying to do a left join so that I get all of my rows from Table 1 even if there is no value corresponding to it in the second table.
My structures are:
Location Table:
ID LocName
1 Trk1
2 Trk2
3 Trk3
4 Unk
Quantity Table:
ID PartID Quantity LocationID
1 1 2 1
2 3 12 2
3 2 6 1
4 6 8 3
5 6 5 1
I am trying to join but also make a query on a specific PartID. My query is:
SELECT
INV_LOCATIONS.ID AS LocationID,
INV_LOCATIONS.NAME AS LocationName,
INV_QUANTITY.QUANTITY AS Quantity
FROM INV_LOCATIONS
LEFT JOIN INV_QUANTITY ON INV_LOCATIONS.ID = INV_QUANTITY.LOCATION_ID
WHERE INV_QUANTITY.PART_ID = 1;
My output right now would be:
ID LocName Quantity
1 Trk1 5
3 Trk3 8
The Desired output is:
ID LocName Quantity
1 Trk1 5
2 Trk2 NULL/0
3 Trk3 8
4 Unk NULL/0
I assume it is because I have the WHERE INV_QUANTITY.PART_ID = 1 and that is forcing it to be in the quantity table. I need to be able to verify it is on the right part but how do I also include it if it doesn't exist. I know I have done something very similar before but I cannot remember which project and so I cannot find the code anywhere.
You need to move the filtering logic to the ON clause:
SELECT il.ID AS LocationID, il.NAME AS LocationName,
iq.QUANTITY AS Quantity
FROM INV_LOCATIONS il LEFT JOIN
INV_QUANTITY iq
ON il.ID = iq.LOCATION_ID AND iq.PART_ID = 1;
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).