Symfony Doctrine createQuery - sql

Suppose I have an entity "events" and "users". Users entity is the owing side of a ManyToMany relation to events. My user can book an event which works fine. Now I try to fetch all events and a "identifier" if a user has booked the event. I try to add the user id to the array if the user has booked. Now I try to get these in one query
$em = $this->getDoctrine()->getManager();
$this->token = $tokenStorage->getToken();
$user = $this->token->getUser()->getId();
$query = $em->createQuery("SELECT e, u.id FROM App\Entity\Events e LEFT JOIN e.users u WITH u.id = :id WHERE e.date >= :dateFirstDay and e.date <= :dateLastDay and e.date > :dateNow ")
->setParameter('dateFirstDay',$dateStartDay->format('Y-m-d'))
->setParameter('dateLastDay',$dateEndDay->format('Y-m-d'))
->setParameter('dateNow',$now->format('Y-m-d'))
->setParameter('id', $user);
$events = $query->getArrayResult();
return new JsonResponse($events);
This gives me the booked event twice. One with id "null" and the other with the (right) user id. How can I avoid to get the event with id "null"? I tried with "GROUP BY e" but that don't work.
Here is my postman output:
{
"0": {
"id": 1,
"name": "Event 1 ",
"date": {
"date": "2021-03-10 15:32:37.000000",
"timezone_type": 3,
"timezone": "Europe/Berlin"
},
"description": "Beschreibungstext",
"duration": "45"
},
"id": null
},
{
"0": {
"id": 1,
"name": "Event 1 ",
"date": {
"date": "2021-03-10 15:32:37.000000",
"timezone_type": 3,
"timezone": "Europe/Berlin"
},
"description": "Beschreibungstext",
"duration": "45"
},
"id": 4
},
Thanks

try adding "AND e.users IS NOT NULL"
anyway I suggest you to consider alternative ways to do this query if you can; think that it's common that a query to a Repository (eg. "Events") should return only instances of Events entity, and not "Events entity + user id" as you are doing with ""SELECT e, u.id"
you could do just just "SELECT e", you will have a list of Events, and then on each entity you should be able to call "$even->getUsers()" if I understood well

Related

Is there anyway to get Telegram Group Admins without joining channel Telethon?

async def get_group_admins(self):
dialogs = await self.get_dialogs()
for dialog in dialogs:
if type(dialog.entity) == Channel:
if dialog.entity.megagroup:
async for user in self.client.iter_participants(
dialog.name, filter=ChannelParticipantsAdmins
):
if not user.bot:
participant = await self.client(
GetParticipantRequest(dialog.id, user.id)
)
if type(participant.participant) == ChannelParticipantCreator:
item = {
"Group Name": dialog.name,
"Name": user.first_name,
"Lastname": user.last_name,
"Telegram Address": "https://web.telegram.org/k/#"
+ str(user.id),
"type" : "creator",
}
else:
item = {
"Group Name": dialog.name,
"Name": user.first_name,
"Lastname": user.last_name,
"Telegram Address": "https://web.telegram.org/k/#"
+ str(user.id),
"type" : "admin",
}
self.listed.append(item)
self.conversations[dialog.name].append(item)
This is the way how i am getting chat admins. But to reach that I need to join that group. Is there any way to get public group admins without joining?

Is there way to return null valued rows when when querying joined table

I have two tables: users table with id, name columns and events table with id, content and userId columns.
I am trying to query a table that return joined information from these two tables with name and events columns where events would represent an array of content fields corresponding to a user.
This is the query I am running:
select
name, group_concat(content) as events
from
users
left join
events on id = userId
group by
userId
order by
id
However rows with null values are not being returned except of just one row. What am I doing wrong?
Users table
[
{
"id": 1,
"name": "Hugo Powlowski"
},
{
"id": 2,
"name": "Jeremy Littel II"
},
{
"id": 3,
"name": "Eleanor King"
},
{
"id": 4,
"name": "Rogelio Jacobson"
},
{
"id": 5,
"name": "Jerald Rowe PhD"
},
{
"id": 6,
"name": "Robyn Tromp"
},
{
"id": 7,
"name": "Norman Zboncak"
},
{
"id": 8,
"name": "Mr. Kristy Orn"
},
{
"id": 9,
"name": "Mrs. Olivia Trantow"
},
{
"id": 10,
"name": "Daniel Lebsack"
}
]
Events table
[
{
"eventId": 3,
"content": "hello",
"userId": 7
},
{
"eventId": 12,
"content": "rulsan berden",
"userId": 1
}
]
Joined table
[
{
"name": "Hugo Powlowski",
"events": "rulsan berden"
},
{
"name": "Jeremy Littel II",
"events": null
},
{
"name": "Norman Zboncak",
"events": "hello"
}
]
You should group by the column in the parent table, not the table being left joined, so that the values will never be null.
So change GROUP BY userid to GROUP BY users.id.
Try to use a nested SELECT, this should return null for the users without any event:
select
u.name,
SELECT(
group_concat(content)
FROM
events
WHERE
userId = u.id
) as events
from
users u
order by
u.id

Dynamic CASE WHEN in Postgresql

I have a list of Conversations, that come from multiple pages as below:
[
{
"id": 1,
"page_id": 1,
"name": "name 1",
"assigned_user_ids": ["user1"]
},
{
"id": 2,
"page_id": 2,
"name": "name 2",
"assigned_user_ids": ["user2"]
},
{
"id": 3,
"page_id": 1,
"name": "name 3",
"assigned_user_ids": ["user2"]
},
{
"id": 4,
"page_id": 2,
"name": "name 4",
"assigned_user_ids": ["user1"]
}
]
Imagine that "User 1" is calling the query, and User 1 can get all items of page_id = 1 (because user 1 is administrator), but in page_id = 2 he/she
only get the items that has been assigned to, in this case is item with id = 4.
So when user 1 query, what I want to received is:
[
{
"id": 1,
"page_id": 1,
"name": "name 1",
"assigned_user_ids": ["user1"]
},
{
"id": 3,
"page_id": 1,
"name": "name 3",
"assigned_user_ids": ["user2"]
},
{
"id": 4,
"page_id": 2,
"name": "name 4",
"assigned_user_ids": ["user1"]
}
]
This is my existing query in SQL look like:
SELECT * FROM Conversations
WHERE PageId IN (1, 2)
Can any one tell me how to modify my SQL to resolve my problem?
Thank you very much!
You can use OR It will either give you what is on page one, so everything from there, or everything that has been assigned to userId 1. So effectively only the things that have been assigned on every other page.
SELECT * FROM Conversations
WHERE PageId = 1 OR userId = 1
If you want to restrict this to only some pages, you can still use IN.
SELECT * FROM Conversations
WHERE PageId = 1 OR userId = 1 AND pageId IN (2,3,4)

Postgres knex query joining columns

I have a Postgres DB that stores data in a table that has the following columns "date | uid | id | value | data".
Using knex on a node.js server I currently get from this query:
data = await db(tableName).select(["date", "uid", "id", "value", "value as market_cap", "data"]).whereIn("id", ["index", "market_cap", "market"]);
the following result:
"data": [
{
"date": "2020-11-07T21:43:11.709Z",
"uid": "nmvdqy0kh87sd8a",
"id": "index",
"value": "999.9999999999999",
"market_cap": "999.9999999999999",
"data": null
},
{
"date": "2020-11-07T21:43:11.709Z",
"uid": "nmvdqy0kh87sd8b",
"id": "market_cap",
"value": "10125616413",
"market_cap": "10125616413",
"data": null
},
{
"date": "2020-11-07T21:43:11.709Z",
"uid": "nmvdqy0kh87sd8c",
"id": "market",
"value": null,
"market_cap": null,
"data": {
"1": [],
"2": []
}
},
...
];
The date pairs are all exactly the same. Data stored under id "market_cap" is actually stored as "value" and data stored under id "market" is actually stored as "data".
Now, what I actually need is:
"data": [
{
"date": "2020-11-07T21:43:11.709Z",
"value": "999.9999999999999",
"market_cap": "10125616413",
"data": {
"1": [],
"2": []
}
},
...
];
Is there a way to obtain this data structure directly from the database instead of transforming the data on the server? Bonus points it you provide the knex query / SQL query. Thank you!
You can accomplish this with a self-join on date and selecting on the rows with certain IDs. Left join ensures a result for each date even if they're missing a data type.
select mv."date", mv.value, mc.value as market_cap, md.data
from market_snapshots mv
left join market_snapshots mc on mv."date" = mc."date" and mc.id = 'market_cap'
left join market_snapshots md on mv."date" = md."date" and md.id = 'market'
where mv.id = 'index';
Try it.
In Knex it would be something like...
knex.select(['mv.date', 'mv.value', 'mc.value as market_cap', 'md.data'])
.from({ mv: 'market_snapshots' })
.leftJoin({ mc: 'market_snapshots' }, function() {
this.on('mv.date', '=', 'mc.date').andOn(knex.raw('mc.id = ?', 'market_cap'))
})
.leftJoin({ md: 'market_snapshots' }, function() {
this.on('mv.date', '=', 'md.date').andOn(knex.raw('md.id = ?', 'market'))
})
.where('mv.id', 'index')

query a json key in postgres json field

Say I have in Postgres stored in JSON field called “data” like this
{
"CUSTA": {
"name": "Customer A",
},
"CUSTB": {
"name": "Customer B",
},
"CUSTC": {
"name": "Customer C",
}
}
How can I query to return the record that contains the key “CUSTA” ? or even better the value of “CUSTA” which is "name": "Customer A"
trying to do something like this but obviously i cant use the keyword key
SELECT * FROM invoices WHERE data->>key = 'CUSTA';
select '{
"CUSTA": {
"name": "Customer A"
},
"CUSTB": {
"name": "Customer B"
},
"CUSTC": {
"name": "Customer C"
}
}'::json#>>'{CUSTA}';
?column?
------------------------------
{ +
"name": "Customer A"+
}
(1 row)
note: you have trailing commas after name:customer x, which is not proper json. For your query, you would probably do something like:
select data#>>'{CUSTA}' from invoices;
or, if data isn't already a json field:
select data::json#>>'{CUSTA}' from invoices;
I don't understand why any invoice would have more than one customer though.
-g