I have a table as follows:
------------------------------------------------------
| row_num | person_id | org_id | other columns |
|-----------|-------------|----------|---------------|
| 0 | person_0 | org_0 | . |
| 1 | person_1 | org_0 | . |
| 2 | person_2 | org_0 | . |
| 3 | person_3 | org_0 | . |
------------------------------------------------------
| 3 | person_0 | org_1 | . |
| 4 | person_1 | org_1 | . |
| 5 | person_2 | org_1 | . |
| 6 | person_3 | org_1 | . |
------------------------------------------------------
| 6 | person_0 | org_2 | . |
| 7 | person_1 | org_2 | . |
| 8 | person_2 | org_2 | . |
| 9 | person_3 | org_2 | . |
------------------------------------------------------
The primary key is (person_id, org_id). This combination is guaranteed to be unique.
Let us say, I have lists person_ids and corresponding org_ids for certain persons and I want to fetch their records from the collection.
persons = [("person_0", "org_0"), ("person_1", "org_1"), ("person_3", "org_1")]
person_ids, org_ids = zip(*persons)
In this case the expected output is columns from rows 0, 4, 6.
I can always find the answer by finding the intersection of the following two queries, but I was wondering if there is any smarter way to do this:
db.collection.find({person_id: {$in: person_ids})
db.collection.find({org_id: {$in: org_ids})
If you need it by OR operator you can do it by this command :
db.collection.find({
$or:[
{person_id: { $in: person_ids } },
{org_id: { $in: org_ids } }
]
})
If you need it by AND operator you can do it by this command :
db.collection.find({
person_id: { $in: person_ids },
org_id: { $in: org_ids }
})
You can find the answer in one query this way
db.collection.find({
person_id: { $in: person_ids },
org_id: { $in: org_ids }
})
Here's simple demo: https://mongoplayground.net/p/TwYxZRDFVBI
Related
Table name: people
+----+------+-------------+-------+
| id | name | city | state |
+----+------+-------------+-------+
| 1 | Joe | Los Angeles | CA |
+----+------+-------------+-------+
| 2 | Jill | Miami | FL |
+----+------+-------------+-------+
| 3 | Asa | Portland | OR |
+----+------+-------------+-------+
Table name: pets
+----+----------+------+
| id | pet_name | type |
+----+----------+------+
| 1 | Spike | dog |
+----+----------+------+
| 1 | Fluffy | cat |
+----+----------+------+
| 2 | Oscar | dog |
+----+----------+------+
How would I join the two tables above to include a column containing JSON of results matched in the 'pets' table (PostgreSQL)?
+----+------+------------------------------------------------------------+
| id | name | pets |
+----+------+------------------------------------------------------------+
| 1 | Joe | [{name:'Spike', type:'dog'}, {name: 'Fluffy', type:'cat'}] |
+----+------+------------------------------------------------------------+
| 2 | Jill | [{name:'Oscar', type:'dog'}] |
+----+------+------------------------------------------------------------+
| 3 | Asa | [] |
+----+------+------------------------------------------------------------+
Use json_agg() to aggregate over json-objects:
SELECT people.id
, name
, json_agg(
CASE WHEN pet_name IS NOT NULL THEN
json_build_object(
'name', pet_name
, 'type', type
)
END
)
FROM people
LEFT JOIN pets ON people.id = pets.id
GROUP BY
people.id
, name
ORDER BY
people.id;
Got my hand dirty on GPS trajectory dataset. This data set consists of sequence of the GPS points of trips for users, until the length of trip:
SELECT * FROM gps_track;
+---------+------------------+------------------+
| user_id | lat | lon |
+---------+------------------+------------------+
| 1 | 39.984702 | 116.318417 |
| 1 | 39.984683 | 116.31845 |
| 1 | 39.984611 | 116.318026 |
| . | . | . |
| 2 | 26.162202 | 119.943787 |
| 2 | 26.161528 | 119.943234 |
| 2 | 26.1619 | 119.943228 |
| . | . | . |
| 3 | 22.8143366666667 | 108.332281666667 |
| 3 | 22.81429 | 108.332256666667 |
| 3 | 22.81432 | 108.332258333333 |
| . | . | . |
| 4 | 32.9239666666667 | 117.386683333333 |
| 4 | 32.9235166666667 | 117.386616666667 |
| 4 | 32.9232833333333 | 117.386683333333 |
| . | . | . |
+---------+------------------+------------------+
I can get the COUNT of GPS points for each user_id 1, 2,3,.. etc.
SELECT distinct user_id
, COUNT(lat) AS lat_count
FROM gps_track
GROUP BY user_id
How do I then get the median of the number of GPS points in all the trips? Not the median point for each user. Here's the fiddle for sample points from my dataset.
Maybe:
SELECT percentile_disc(0.5) WITHIN GROUP (ORDER BY lat_count)
FROM (SELECT user_id
, COUNT(lat) AS lat_count
FROM gps_track
GROUP BY user_id) du;
I have a table like this in database
+---+-------------+--------------+
|id | service_name| doc_id |org_id|
+---+-------------+--------------+
| 1 | new service | 12 | 119 |
| | | | |
| 2 | new service | 24 | 119 |
| | | | |
| 3 | old service | 13 | 118 |
| | | | |
| 4 | old service | 14 | 118 |
| | | | |
| 5 | new service | 20 | 119 |
+---+-------------+--------------+
I want to group all the doc_id's according to service_name column
I have tried using
IN my controller
$where_person['org_id'] = $this->post('org_id');
$result_insert = $this->$model_name->fetch_doctor_services($where_person);
In my Model
function fetch_doctor_services($where){
$this->db->select('service_name,doc_id')->from('services');
$this->db->group_by('service_name');
$this->db->where($where);
return $this->db->get()->result();
}
But it does not output data as i desire, by grouping by service_name and all the doc_id's according to that service_name.
where am i going wrong here?
Currently my output is like this.
{ "data":
[ { "service_name": "new service", "doc_id": "12" },
{
"service_name": "old service", "doc_id": "13" }
]
}
You need to use GROUP_CONCAT. See below code on how to use it
$this->db->select('service_name, GROUP_CONCAT( doc_id) ')->from('services');
$this->db->group_by('service_name');
$this->db->where($where);
return $this->db->get()->result();
I have a table called places_log. The schema for places logs is as follows
{
'type': {
'type': 'string',
'required': True,
'allowed': ['in', 'out']
},
'fence_name': {
'type': 'string',
'required': True
},
'time': {
'type': 'datetime',
'required': True
}
}
When a query to get all the documents of this table sorted by fence name and time is made, say the output is as follows
+------------+---------+-----------+
| fence_name | type | time |
+------------+---------+-----------+
| abc | in | 08:30 |
| abc | in | 08:32 |
| abc | out | 09:45 |
| abc | in | 15:18 |
| abc | out | 16:20 |
| abc | out | 16:25 |
| lmn | in | 12:30 |
| pqr | in | 12:40 |
| pqr | out | 13:52 |
| pqr | out | 13:58 |
| xyz | out | 19:43 |
| xyz | out | 19:45 |
+-------------+--------+-----------+
I want a query which will return the following result. For each fence, when there are simultaneous ins, I want the latest in and when there are simultaneous outs, I want the latest out.
+------------+---------+-----------+
| fence_name | type | time |
+------------+---------+-----------+
| abc | in | 08:32 |
| abc | out | 09:45 |
| abc | in | 15:18 |
| abc | out | 16:25 |
| lmn | in | 12:30 |
| pqr | in | 12:40 |
| pqr | out | 13:58 |
| xyz | out | 19:45 |
+-------------+--------+-----------+
Basically there is a feature where the user can create multiple fences on the map we will store the times when the user's vehicle enters or exits the fence. Due to some edge cases, we are getting multiple 'in' events simultaneously without an 'out' event which is not possible. So I am trying to come up with a query where I can only take the last 'in' event (when there are simultaneous ins) and take that time as the time when the vehicle entered the fence.
But the vehicle can enter and exit a fence multiple times. So I have to get all those ins and outs also
Doing an aggregation using group and last will not consider ins and outs which are not simultaneous, for the following aggregation
[
{ "$sort": { "fence_name": 1, "time": 1 } },
{
'$group': {
"_id": {
"fence_name": "$fence_name",
"type": "$type"
},
"time": {
"$last": "$time"
}
}
}
]
We will get a something like this
+------------+---------+-----------+
| fence_name | type | time |
+------------+---------+-----------+
| abc | in | 15:18 |
| abc | out | 16:25 |
| lmn | in | 12:30 |
| pqr | in | 12:40 |
| pqr | out | 13:58 |
| xyz | out | 19:45 |
+-------------+--------+-----------+
Here, I don't get the second time the vehicle entered and exited the fence 'abc'
I want to get multiple ins and outs which are not simultaneous.
And even better if I can get something like this
+------------+---------+-----------+
| fence_name | in | out |
+------------+---------+-----------+
| abc | 08:32 | 09:45 |
| abc | 15:18 | 16:25 |
| lmn | 12:30 | null |
| pqr | 12:40 | 13:58 |
| xyz | null | 19:45 |
+-------------+--------+-----------+
I have a table posts as follows:
+------+--------+-----------+---------+------------+
| id | title | category | visits | content |
+------+--------+-----------+---------+------------+
| 1 | aaa | 1 | 44 | Text co... |
| 2 | bbb | 1 | 63 | Text co... |
| 3 | ccc | 2 | 42 | Text co... |
| 4 | ddd | 2 | 65 | Text co... |
| 5 | eee | 2 | 73 | Text co... |
| 6 | fff | 3 | 57 | Text co... |
| 7 | ggg | 3 | 79 | Text co... |
| 8 | hhh | 3 | 62 | Text co... |
| 9 | iii | 2 | 46 | Text co... |
| 10 | jjj | 4 | 64 | Text co... |
| 11 | kkk | 4 | 76 | Text co... |
+------+--------+-----------+---------+------------+
I am trying to obtain the most visited posts in each category along with their data like id, title and content.
With the below query I am able to obtain an entry for each category
db.posts.aggregate([
{"$group": {
"_id": "$category",
"count": {"$sum": 1},
"max-visits": { $max: "$visits" }
}}
]);
I am able to obtain the category along with maximum of visitors of that category and the no of posts in it. But I also require id, title and content of the post that has maximum visits.
Expected output:
+------+--------+----------------+---------+------------+
| id | title | category(_id) | visits | content |
+------+--------+----------------+---------+------------+
| 1 | bbb | 1 | 63 | Text co... |
| 2 | eee | 2 | 73 | Text co... |
| 3 | ggg | 3 | 79 | Text co... |
| 4 | kkk | 4 | 76 | Text co... |
+------+--------+----------------+---------+------------+
Actual output:
+-----------------+--------+-------------+
| category(_id) | count | max-visits |
+-----------------+--------+-------------+
| 1 | 2 | 63 |
| 2 | 4 | 73 |
| 3 | 3 | 79 |
| 4 | 2 | 76 |
+-----------------+--------+-------------+
You should $sort before $group then you can easily get $first document's fields.
db.posts.aggregate([
{"$sort": { category: 1, visits: -1 }},
{"$group": {
"_id": "$category",
"count": {"$sum": 1},
"max-visits": { $max: "$visits" },
"doc_id": { $first: "$_id" },
"title": { $first: "$title" },
"content": { $first: "$content" }
}}
]);