JOIN 2 tables based on req.query in a 3rd table - sql

I have 3 tables (deals, deals_media, access_to_deals)
deals deals_media access (to deals)
name pic_url type media_url deal_id customer_id deal_id
deal1 http://blah video url. 1 1 1
deal2 http://blah2 img url2. 1 1 2
deal3 http://blah3 video url3. 2 2 1
I'm sending an api get request with a customer_id query parameter.
I want to send back an array of objects with all the deals data the customer is eligible for and to join an array of matching deals_media to the deals.id
I'm using sequalize and await functions and my query looks like:
sync (req, res) => {
try {
const customerId = req.query.customer_id;
let deals = await db.sequelize.query(
'SELECT DISTINCT deals.* FROM deals \n' +
'JOIN access ON deals.id = access.deals_id AND access.customerId=$1 \n' +
'LEFT JOIN media ON deals.id = media.deals_id \n',
{ bind: [customerId], type: 'RAW' },
);
res.send(campaign[0]);
} catch (err) {...}
};
my response data looks like:
{
"id":1,
"deal_name": "deal1",
"other data": "data",
"media type": "video",
"media URL": "https://www.......",
"deals_id": 1
},
{
"id":2,
"deal_name": "deal1",
"other data": "data",
"media type": "picture",
"media URL": "https://www.......",
"deals_id": 1
},
{
"id":3,
"deal_name": "deal1",
"other data": "data",
"media type": "audio",
"media URL": "https://www.......",
"deals_id": 1
}
]
and I'd prefer it came out as:
{
"id":1,
"deal_name": "deal1",
"other data": "data",
"media": [
{
"media type": "video",
"media URL": "https://www......."
},
{
"media type": "picture",
"media URL": "https://www......."
},
{
"media type": "audio",
"media URL": "https://www......."
}
]
I've tried to change the last join to 'LEFT JOIN media ON deals.id = media.deals_id GROUP BY media.deals_id \n' however I get an error to include deals.id and media.id to the GROUP BY and then it produces the same incorrect query result as above. I'm relatively new to SQL so any direction is greatly appreciated. Many thanks for considering my request.
UPDATE: As to #NBK's suggestion, I've updated the query below however I'm running into the following error Error is Deals: SequelizeDatabaseError: schema "deals" does not exist
'SELECT json_build_object ( \n' +
"'id', deals.id \n" +
"'deals_name', deals.deals_name \n" +
"'deals_icon_url', deals.deals_icon_url \n" +
"'conversion_event', deals.conversion_event \n" +
"'created_at', daels.created_at \n" +
"'updated_at', deals.updated_at \n" +
"'deleted_at', deals.deleted_at \n" +
"'media', json_build_array ( \n" +
"json_build_objecty ( \n" +
"'media_type', media.media_type \n" +
"'media_url', media.media_url \n" +
') \n' +
') \n' +
') \n' +
'FROM deals \n' +
'INNER JOIN access ON access.deals_id = deals.id AND access.user_id=$1\n' +
'INNER JOIN media ON media.deals_id = deals.id \n',

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?

Using upsert in postgres with a json file in nodejs

I have a large json file of data which I want to put into my database. Some of the object are duplicates, so I want to update the data in case the row is already in the database. Here is my code:
const FILE_PATH = path.join(__dirname, "../../files/apps.json");
const columns = [
"name",
"description",
"ext_id"
];
const myFile = fs.readFileSync(FILE_PATH, { encoding: "utf-8" });
const appData = await models.sequelize.query(
`
INSERT INTO data (${columns.join(", ")})
SELECT ${columns.join(", ")}
FROM (:path)
ON CONFLICT (ext_id)
DO UPDATE SET
${columns.map(col => `${col} = EXCLUDED.${col}`).join(", ")}
RETURNING ext_id;
`,
{ replacements: { path: FILE_PATH } }
);
As you can see, I want to read the file directly and put it into the database. I use a mapper called sequelize, but use a raw query in this case. My immediate problem is that I get this error:
syntax error at or near "'/home/blub/filePath'"
I don't really know how I should specify the path. I tried to parse it in directly, but then the program complained about the /. Any help here? In addition, I am also not sure whether the query is syntactically correct.
Here is a solution using CTE of postgres.
Versions:
"sequelize": "^5.21.3"
postgres:9.6
apps.json:
[
{
"name": "app-a",
"description": "app a desc",
"ext_id": 1
},
{
"name": "app-b",
"description": "app b desc",
"ext_id": 2
},
{
"name": "app-c",
"description": "app c desc",
"ext_id": 3
}
]
index.ts:
import { sequelize } from '../../db';
import { Model, DataTypes, QueryTypes } from 'sequelize';
import fs from 'fs';
import path from 'path';
class Data extends Model {}
Data.init(
{
name: DataTypes.STRING,
description: DataTypes.STRING,
ext_id: {
type: DataTypes.INTEGER,
unique: true,
},
},
{ sequelize, tableName: 'data' },
);
(async function test() {
try {
await sequelize.sync({ force: true });
const FILE_PATH = path.join(__dirname, './apps.json');
const columns = ['name', 'description', 'ext_id'];
const myFile = fs.readFileSync(FILE_PATH, { encoding: 'utf-8' });
const appData = await sequelize.query(
`
with app_json(doc) as (
values ('${myFile}'::json)
)
insert into data (${columns.join(', ')})
select ${columns.join(', ')}
from app_json l
cross join lateral json_populate_recordset(null::data, doc) as p
on conflict (ext_id) do update
set ${columns.map((col) => `${col} = EXCLUDED.${col}`).join(', ')}
returning ext_id;
`,
{ type: QueryTypes.INSERT },
);
console.log(appData);
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
The execution result:
Executing (default): DROP TABLE IF EXISTS "data" CASCADE;
Executing (default): DROP TABLE IF EXISTS "data" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "data" ("id" SERIAL , "name" VARCHAR(255), "description" VARCHAR(255), "ext_id" INTEGER UNIQUE, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'data' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): with app_json(doc) as (
values ('[
{
"name": "app-a",
"description": "app a desc",
"ext_id": 1
},
{
"name": "app-b",
"description": "app b desc",
"ext_id": 2
},
{
"name": "app-c",
"description": "app c desc",
"ext_id": 3
}
]'::json)
)
insert into data (name, description, ext_id)
select name, description, ext_id
from app_json l
cross join lateral json_populate_recordset(null::data, doc) as p
on conflict (ext_id) do update
set name = EXCLUDED.name, description = EXCLUDED.description, ext_id = EXCLUDED.ext_id
returning ext_id;
[ [ { ext_id: 1 }, { ext_id: 2 }, { ext_id: 3 } ], 3 ]
Check the data records in the database:
id name description ext_id
1 app-a app a desc 1
2 app-b app b desc 2
3 app-c app c desc 3

Create parent-children query from many-to-many relationship

Good day,
I struggle to create a query in Postgres to obtain a many-to-many relationship in parent-children form.
There are two tables:
'Projects'
projects table
'Services'
services table
They are connected with the third project_service table
project_service
The query SELECT projects.id_project, projects.title, projects.level, services.id_service, services.service FROM projects, services, project_service WHERE projects.id_project = project_service.id_project AND services.id_service = project_service.id_service return this table:
query result table
How to write a query to get this table in parent-children form like this:
[
{ "id": "1000", "level": "Projects", "title": "Project 1", "children": [
{ "id": "2000", "service": "Service 1},
{ "id": "2001", "service": "Service 2},
{ "id": "2002", "service": "Service 3},
{ "id": "2003", "service": "Service 4}
]},
{ "id": "1001", "level": "Projects", "title": "Project 2", "children": [
{ "id": "2004", "service": "Service 5}
]}]
Thank you for help
Is this what you mean?
with svc_json as (
select id_service, to_jsonb(services) as svc
from services
), together as (
select p.*, jsonb_agg(s.svc) as children
from project_service ps
join svc_json s on s.id_service = ps.id_service
join projects p on p.id_project = ps.id_project
group by p.id_project, p.title, p.level
)
select jsonb_pretty(jsonb_agg(to_jsonb(together)))
from together;
jsonb_pretty
-----------------------------------------
[ +
{ +
"level": "Projects", +
"title": "Project 1", +
"children": [ +
{ +
"service": "Service 1",+
"id_service": 2000 +
}, +
{ +
"service": "Service 2",+
"id_service": 2001 +
}, +
{ +
"service": "Service 3",+
"id_service": 2002 +
}, +
{ +
"service": "Service 4",+
"id_service": 2003 +
} +
], +
"id_project": 1000 +
}, +
{ +
"level": "Projects", +
"title": "Project 2", +
"children": [ +
{ +
"service": "Service 5",+
"id_service": 2004 +
} +
], +
"id_project": 1001 +
} +
]
(1 row)

Is there any way to insert below nested json data into sql server

I am working on a nested JSON data which I need to load into SQL SERVER 2012. The nested JSON contains two roots i.e. one column and another rows. I need to put value from row into the column. Please see the structure as below:
{
"tables": [
{
"name": "PrimaryResult",
"columns": [
{
"name": "timestamp",
"type": "datetime"
},
{
"name": "id",
"type": "string"
},
{
"name": "name",
"type": "string"
},
{
"name": "url",
"type": "string"
},
{
"name": "duration",
"type": "real"
}
],
"rows": [
[
"2019-04-08T13:09:52.871Z",
"244",
"Internal",
"https://google.com",
1245,
]
]
}
]
}
Result:
timestamp id name url duration
2019-04-08 244 Internal https://google.com 1245
Here , in sql server it should take column names from columns and value for each column from rows
assuming that you store the json into a file named json.txt
import json
with open('json.txt') as f:
data = json.load(f)
tableName = data['tables'][0]["name"]
sqlCreateTable = 'CREATE TABLE ' + tableName + ' (\n'
sqlInsertInto = 'INSERT INTO ' + tableName + ' ('
for i in range(0,len(data['tables'][0]['columns'])):
columnName = data['tables'][0]['columns'][i]['name']
type = data['tables'][0]['columns'][i]['type']
sqlCreateTable += columnName + " " + type + ',\n'
sqlInsertInto += columnName + ', '
sqlCreateTable = sqlCreateTable[:-2] + '\n);'
sqlInsertInto = sqlInsertInto[:-2] + ')\nVALUES ('
for value in data['tables'][0]['rows'][0]:
sqlInsertInto += str(value) + ', '
sqlInsertInto = sqlInsertInto[:-2] + ');'
print(sqlCreateTable)
print(sqlInsertInto)
Output for create table:
CREATE TABLE PrimaryResult (
timestamp datetime,
id string,
name string,
url string,
duration real
);
Output for insert into table:
INSERT INTO PrimaryResult (timestamp, id, name, url, duration)
VALUES (2019-04-08T13:09:52.871Z, 244, Internal, https://google.com, 1245);

How to search Host Groups in Zabbix API

I want to list all Host Groups that match some search criteria.
I've tried that:
data = '{"jsonrpc": "2.0",
"method": "hostgroup.get",
"params": {
"output": "extend",
"search": {
"name": [
"' + group_name + '"
]
},
},
"id":' + str(msg_id) + ',
"auth": "' + auth + '"
}'
But that is not a correct syntax.
I also tried this:
data = '{"jsonrpc": "2.0",
"method": "hostgroup.get",
"params": {
"output": "extend",
"filter": {
"name": [
"' + group_name + '"
]
},
},
"id":' + str(msg_id) + ',
"auth": "' + auth + '"
}'
This one works, but it only matches exactly the group name. And, so, it always returns 1 or 0 matches.
I tried adding the "options":"searchWildcardsEnabled" option in this last query, but it didn't make a difference in the result (i.e. it didn't produce multiple groups as output).
I've found the correct way. I'll post it here in case anyone else needs it later.
data = '{"jsonrpc": "2.0",
"method": "hostgroup.get",
"params": {
"output": "extend",
"search": {
"name": [
"' + group_name + '"
]
}
},
"id":' + str(msg_id) + ',
"auth": "' + auth + '"
}'
You don't need to specify the wildcard, it's default. Also, you don't need to put the % inside your query.