I have a "messages" table with columns: "id", "title",
"categories" table with columns: "id", "title",
and "messages_categories" link table with columns: "message_id","category_id".
lets assume we have messages with ids of
1,2,3
and categories with ids of
1,2,3
messages_categories with data of
message: 1, category: 1
message: 2, category: 1
message: 2, category: 2
message: 3, category: 1
message: 3, category: 2
message: 3, category: 3
I want to find the exact match or more for example
if I search for category 1 i'll get messages 1,2,3
if I search for category 1,2 i'll get messages 2,3
if I search for category 1,2,3 i'll get only message 3
i'm using a lot of ids so join for every category can be too much.
I figured out I can use "having" statement with "sum" and "count" to find the exact rows
but it's not good enough.
Appreciate any help, Nevo.
If you need "more" then use NOT EXISTS, so called relational division with reminder.
SELECT DISTINCT messages_id
FROM messages_categories r1
WHERE NOT EXISTS
(SELECT *
FROM
(SELECT 1 as cat_id UNION SELECT 2 ) S -- id of categories needed
WHERE NOT EXISTS
(SELECT *
FROM messages_categories AS r2
WHERE (r1.messages_id = r2.messages_id)
AND (r2.category_id = S.cat_id)));
Something along the lines of this might work:
SELECT DISTINCT x.message_id
FROM (
**query-that-gives-the-exact-rows-but-isnt-good-enough**
) AS x
Related
I am working with a dataset, I used GROUP BY to get the count of one of the columns. Then, I want to filter the columns with count > 2, I find that WHERE does not work after GROUP BY, may I ask what should I do?
For example, for the id_table with only one column id with the numbers [2, 3, 2, 3, 4, 2], I want to count each and find which id appears more than two times, in this case, the output should be 2 since it appeared 3 times. My code is like below:
SELECT id
FROM id_table
GROUP BY id
WHERE count(id) > 2;
The error code is: near "WHERE": syntax error
Try this (HAVING instead of WHERE):
SELECT id
FROM id_table
GROUP BY id
HAVING count(id) > 2
;
Let's assume I have the table with below columns and records:
id shop_id product_id
1 1 1
2 1 2
3 2 1
4 2 3
I want to run single query to get ID 1 and ID 4 records when query looks like this:
ShopProduct.where(shop_id: 1, product_id: 1).where(shop_id: 2, product_id: 3)
The problem is when I try to simplify like this:
ShopProduct.where(shop_id: [1,2], product_id: [1,3])
Then I get three records, not two as expected.
A simple solution for few input pairs: ROW values:
SELECT *
FROM "ShopProduct"
WHERE (shop_id, product_id) IN ((1,1), (2,3));
Related:
SQL syntax term for 'WHERE (col1, col2) < (val1, val2)'
If you have two long arrays you want to process in "lock-step", other forms may be faster / more convenient. Like: unnest two arrays in parallel (in lock-step), then join:
SELECT *
FROM unnest('{1,2}'::int[], '{1,3}'::int[]) t(shop_id, product_id)
JOIN "ShopProduct" USING (shop_id, product_id);
There is an overloaded version of the function unnest() that accepts multiple input arrays. See:
Unnest multiple arrays in parallel
db<>fiddle here
You can achieve it with or condition starting from rails 5
ShopProduct.where(shop_id: 1, product_id: 1).or(ShopProduct.where(shop_id: 2, product_id: 3))
Related:
Rails find records using an array of hashes
I am working on a hotel management software and I need to display floors and the rooms on that floor......
I have a wing_master table in the database with following columns -:
wing_id,
wing_name,
floor,
floor_room_count,
status
Its like I have a record for one wing in that hotel which has 4 floors, but when I write a query to get the floors in that wing it just gives me "4" as the result in sql.....
I want the query to return it as follows -:
1
2
3
4
I want it this way so that I can use nested data-list control in asp.net....
My query is "select floors from wing_master where wing_id = 1"
For most databases (not MySQL), you can use a recursive query to obtain all floors:
with all_floors as (
select floors from wing_master where wing_id = 1
union all
select floors - 1 as floors from all_floors
where floors > 1
)
select * from all_floors order by floors;
SQLFiddle example.
In MySQL, the easiest way would be to create a numbers table that has a sequence of numbers up to the highest possible floor. Then join to that table to get all floors:
select num from wing_master
join numbers on
wing_id = 1 and
num <= floors;
SqlFiddle example.
Your query is ok, and also it seems that query and table structure will be fulfilling your requirements. can you show your data, because as per the structure, there should be four rows in the table, showing floor 1, 2, 3, 4
something like this
floor wing_id
1 1
2 1
3 1
4 1
If that is how your data looks, then your query must be ok, else there is some other issue. so do share your structure with few rows of data.
I am trying to select the most recent record between 2 users based on a to_number and a from_number and created date/time.
Once the record is found, display the message and time stamp. As long as either the to_number or from_number have the same pairing, then that is the message I want to display.
I'm really getting stuck on finding unique to/from OR from/to records with the same number combinations AND that haven't been listed before.
My data:
Messages table:
"id","to_number","from_number","message","created_at","dm_user_id"
"1","7325551212","5705551234","new update","2011-12-17T11:26:33-05:00","1"
"2","5705551234","3015551212","next update","2011-12-17T11:26:53-05:00","1"
"3","6095559876","4695551212","trying messages.","2011-12-19T19:20:47-05:00","2"
"4","5705551234","4155551212","did i get this?","2011-12-19T20:04:40-05:00","1"
"5","9075551212","5705551234","Where did this go?","2011-12-19T20:05:51-05:00","1"
"6","9075551212","5705551234","testing","2011-12-19T20:12:53-05:00","1"
"7","3015551212","5705551234","Are you here ","2011-12-19T20:13:34-05:00","1"
"8","6175554567","4695551212","test from app","2011-12-19T22:51:32-05:00","2"
From the above data, I only want the following records, listed newest to oldest.
NOTE: Not all records will be returned because there are duplicate to/from combinations. For example, id 2 and id 7 are messages between the same 2 numbers. Only the most recent will be returned, id 7.
Another example is id 5 and id 6 - they are both to/from the same numbers so only the most recent is returned, id 6.:
for dm_user_id=1
"3015551212", "Hello", "2011-12-19T20:13:34-05:00" # id 7
"9075551212", "testing", "2011-12-19T20:12:53-05:00" # id 6
"4155551212", "did i get this?", "2011-12-19T20:04:40-05:00" # id 4
"7325551212", "new update", "2011-12-17T11:26:33-05:00" # id 1
for dm_user_id=2
"6175554567", "test from app", "2011-12-19T22:51:32-05:00" # id 8
"6095559876", "trying messages.", "2011-12-19T19:20:47-05:00" # id 3
I'm trying different combinations of GROUP BY and DISTINCT, but not getting the results I'm looking for.
select * from messages where dm_user_id = 1
group by to_number, from_number
select * from (
select DISTINCT to_number, from_number dm_user_id
from messages) where dm_user_id = 1
With a dm_users table, you want this:
select
m.*
from
dm_users u1
cross join dm_users u2
inner join messages m on
u1.phone_number in (m.to_number, m.from_number)
and u2.phone_number in (m.to_number, m.from_number)
where
u1.dm_user_id = 1
and u2.dm_user_id = 2
order by
m.created_at desc
This is a common question, basically you want the most recent message from each number, either TO or FROM, but you don't want duplicates. You may find something useful in this category greatest-n-per-group
The working SQL that returns only 1 most recent message for a given to/from, from/to number pair and sorts with most recent first. Modified the SQL from this link.
SELECT
fullMessage.id,
fullMessage.to_number,
fullMessage.from_number,
fullMessage.message,
fullMessage.dm_user_id
FROM
messages fullMessage JOIN
(
SELECT max(id) as MAX_ID, to_number, from_number
FROM messages WHERE dm_user_id = 1 # this can be changed for any dm_user_id
GROUP BY from_number, to_number
) maxMessage ON maxMessage.MAX_ID = fullMessage.id
ORDER BY fullMessage.id desc;
I have some data I am querying. The table is composed of two columns - a unique ID, and a value. I would like to count the number of times each unique value appears (which can easily be done with a COUNT and GROUP BY), but I then want to be able to count that. So, I would like to see how many items appear twice, three times, etc.
So for the following data (ID, val)...
1, 2
2, 2
3, 1
4, 2
5, 1
6, 7
7, 1
The intermediate step would be (val, count)...
1, 3
2, 3
7, 1
And I would like to have (count_from_above, new_count)...
3, 2 -- since three appears twice in the previous table
1, 1 -- since one appears once in the previous table
Is there any query which can do that? If it helps, I'm working with Postgres. Thanks!
Try something like this:
select
times,
count(1)
from ( select
id,
count(distinct value) as times
from table
group by id ) a
group by times