I have a fairly simple MySQL situation. There's a table with JSON values in it that I want to find the max of.
Something like this:
ID | data
1 | { value: 1 }
1 | { value: 2 }
1 | { value: 3 }
2 | { value: 4 }
...
When I query via something simple like this:
SELECT id, max(data->'$.value')
FROM table
GROUP BY id
I'm getting simply wrong values. Something like:
ID | max...
1 | 2
2 | 4
When I debug my query by dropping in a group_concat to see what's being aggregating over:
SELECT id, group_concat(data->'$.value'), max(data->'$.value')
FROM table
GROUP BY id
Suddenly the max function returns the right value and the group_concat shows the list of values it theoretically should be maximizing over.
What's going on? A quick search reveals very little. Thanks!
Related
I understand that I can use the value in insert into to insert multiple rows by columns but my case is a bit different:
I have a string that looks like this: "2,5,14,25,30".
And a connection table that has 2 columns: (INT UserId, INT GroupId).
Let's say I want to connect userId = 1 with all the IDs in the string, how should I do that?
I am familiar with the FIND_IN_SET() function that helps me search for those IDs, but I can't figure how to use it in this case.
In the end, I want my table to look like this:
UserId | GroupId
-----------------
1 | 2
1 | 5
1 | 14
1 | 25
1 | 30
I have the query to search for ids in jsonb column, the array can contain many id's.
Say I have data like this
id | act | act_id | from_ids | object_ids | post_date
2 post 1 {"2":"1494308197","3":"1494308198","4":"1494308199"} {"items":["104564"]} 1494308197
And a query like this
SELECT an.*
FROM activity_network an
WHERE an.from_ids ?| ARRAY['2','3'];
That query will return the row because it finds 2 and 3. But how can I return what it finds in it's own column. So that it returns 2,3 in text or json format or something like that in the results as well.
I tried this
SELECT an.*, jsonb_each_text(from_ids) b
FROM activity_network an
WHERE an.from_ids ?| ARRAY['2','3'];
But that creates 3 rows with a b column each one with the value 2, 3 and 4. I want 1 row with b column containing both 2 and 3 which is what I searched on.
Is that possible?
example result that I'm looking for. notice the last column. I put it as column delimited for demo purpose. it can be any format I can use.
2 | post | 1 | {"2":"1494308197","3":"1494308198","4":"1494308199} | {"items":["104564"]} | 1494308197 | 2,3}
here I explode/implode it. Quite ugly way.
t=# with p as (
with c as (
select '{"2":"1494308197","3":"1494308198","4":"1494308199"}'::json j
)
select json_object_keys(j),j->json_object_keys(j) v
from c
)
select concat('{',string_agg(concat('"',json_object_keys,'"',':',v)::text,','),'}')::json
from p
where json_object_keys::int = ANY (ARRAY [2,4]);
concat
-------------------------------------
{"2":"1494308197","4":"1494308199"}
(1 row)
Time: 0.348 ms
The function jsonb_exists_all sounds like what you want. It requires that all the elements in the array exist as top-level keys in the object.
You can find that and other undocumented functions for jsonb using the \df *jsonb* command in psql.
example paste:
test=# SELECT * from twj WHERE jsonb_exists_any(from_ids, ARRAY['2','3']);
id | act | from_ids
----+------+-----------------------------------------------------------
1 | post | {"2": "1494308197"}
3 | post | {"2": "1494308197", "3": "1494308198", "4": "1494308199"}
(2 rows)
test=# SELECT * from twj WHERE jsonb_exists_all(from_ids, ARRAY['2','3']);
id | act | from_ids
----+------+-----------------------------------------------------------
3 | post | {"2": "1494308197", "3": "1494308198", "4": "1494308199"}
(1 row)
The ?| operator you are using calls the jsonb_exists_any function.
I'm trying create a MySQL query which will return a row (or more, but I'm only interested in a single row) an area suggestion when provided with a postcode.
So, I have a table like so
area_id | postcode_start
1 | NE
2 | DL
3 | DL1
4 | DL2
5 | DL6
...
And I wish to provide a postcode, for example DL5 8TB and for it to return the row 1 | DL as the first characters match.
Another example DL6 4GH would return two rows, 5 | DL6 and 2 | DL
SELECT *
FROM (`area_postcodes`)
WHERE CONCAT(LOWER(`area_postcodes`.`postcode_start`),'%')
LIKE 'dl5 8tb';
Apparently it's a valid query but it always returns an empty set.
You'll see I've added the wildcard % to the other side of the query but it doesn't seem to work and I don't know where else to even consider guessing how to go about it, it's almost like the reverse of a normal MySQL LIKE query.
You were very close:
SELECT
*
FROM
area_postcodes
WHERE
'dl5 8tb' LIKE CONCAT(postcode_start, '%');
I have a table (pretty big one) with lots of columns, two of them being "post" and "user".
For a given "post", I want to know which "user" posted the most.
I was first thinking about getting all the entries WHERE (post='wanted_post') and then throw a PHP hack to find which "user" value I get the most, but given the large size of my table, and my poor knowledge of MySQL subtle calls, I am looking for a pure-MySQL way to get this value (the "user" id that posted the most on a given "post", basically).
Is it possible ? Or should I fall back on the hybrid SQL-PHP solution ?
Thanks,
Cystack
It sounds like this is what you want... am I missing something?
SELECT user
FROM myTable
WHERE post='wanted_post'
GROUP BY user
ORDER BY COUNT(*) DESC
LIMIT 1;
EDIT: Explanation of what this query does:
Hopefully the first three lines make sense to anyone familiar with SQL. It's the last three lines that do the fun stuff.
GROUP BY user -- This collapses rows with identical values in the user column. If this was the last line in the query, we might expect output something like this:
+-------+
| user |
+-------+
| bob |
| alice |
| joe |
ORDER BY COUNT(*) DESC -- COUNT(*) is an aggregate function, that works along with the previous GROUP BY clause. It tallies all of the rows that are "collapsed" by the GROUP BY for each user. It might be easier to understand what it's doing with a slightly modified statement, and it's potential output:
SELECT user,COUNT(*)
FROM myTable
WHERE post='wanted_post'
GROUP BY user;
+-------+-------+
| user | count |
+-------+-------+
| bob | 3 |
| alice | 1 |
| joe | 8 |
This is showing the number of posts per user.
However, it's not strictly necessary to actually output the value of an aggregate function in this case--we can just use it for the ordering, and never actually output the data. (Of course if you want to know how many posts your top-poster posted, maybe you do want to include it in your output, as well.)
The DESC keyword tells the database to sort in descending order, rather than the default of ascending order.
Naturally, the sorted output would look something like this (assuming we leave the COUNT(*) in the SELECT list):
+-------+-------+
| user | count |
+-------+-------+
| joe | 8 |
| bob | 3 |
| alice | 1 |
LIMIT 1 -- This is probably the easiest to understand, as it just limits how many rows are returned. Since we're sorting the list from most-posts to fewest-posts, and we only want the top poster, we just need the first result. If you wanted the top 3 posters, you might instead use LIMIT 3.
i know it may be very simple query, but please help me out.
i have item id 1,2,3,4 etc....
now i want to get all row regrading that item id
what will be mysql query?? i used IN operator but this return only one row
SELECT item_id,item_name FROM tbl_item_detail WHERE item_id IN('1,3,4')
my table structure is below
item_id | item_name |.....
1 | first |
2 | second |
3 | third |
4 | fourth |
. .
which operator i have to use?or what will be perfect query for this?
After firing this query, mysql would have returned two things:
1. The item_id, item_name of the row with id 1 in the tbl_item_detail table.
2. A warning after the above result like, '1 row in set, 3 warnings (0.00sec)'.
The warning message means that there was a problem in your query, and mysql could only partially understand it. Your query was:
SELECT item_id,item_name FROM tbl_item_detail WHERE item_id IN('1,3,4');
It should actually be:
SELECT item_id,item_name FROM tbl_item_detail WHERE item_id IN(1,3,4);
OR
SELECT item_id,item_name FROM tbl_item_detail WHERE item_id IN('1','3','4');
I believe the rest is self explanatory.