Hi hi I have a Nodejs server and I am using PostgreSQL, the bottom part of my database.
How can I select data and represent it like this (in one sql query):
{lessons: ['lesson1','lesson2'], tests: [{quest:'quest_name',options:['opt1','opt2']}]}
I wrote a request but it is far from what I need:
SELECT tests.id,
chapter,
time,
ARRAY_AGG(quests.question) AS questions,
ARRAY_AGG(options.option) AS quest_options
FROM tests
LEFT JOIN quests ON tests.id = quests.test_id
LEFT JOIN options ON quests.id = options.quest_id
WHERE tests.course_id = '${courseId}'
GROUP BY tests.id
You can use a cte to first build the question JSON data, and then aggregate the latter with the lessons:
with tests(q, o) as (
select q.question, json_agg(o.option)
from tests t join quests q on t.id = q.test_id join options o on q.id = o.quest_id
where t.course_id = '${courseId}'
group by q.question
)
select json_build_object('lesson',
(select json_agg(l.lesson_text) from lessons l where l.course_id = '${courseId}'),
'tests',
(select json_agg(json_build_object('quest', t.q, 'options', t.o)) from tests t)
)
Related
I need to compare query results against a table. I have the following query.
select
i.person_id,
a.appellant_first_name,
a.appellant_middle_name,
a.appellant_last_name,
s.*
from CWLEGAL.individuals i inner join CWLEGAL.tblappealsdatarevisionone a
on i.casenm = a.D_N_NUMBER1 and
i.first_name = a.appellant_first_name and
i.last_name = a.appellant_last_name
inner join CWLEGAL.tblappealstosupremecourt s
on a.DATABASEIDNUMBER = s.DBIDNUMBER
order by orclid21;
I need to see what orclid21's in cwlegal.tblappealstosupremecourt don't appear in the above query.
I was able to get this to work.
select
i.person_id,
a.appellant_first_name,
a.appellant_middle_name,
a.appellant_last_name,
s.*
from CWLEGAL.tblappealstosupremecourt s
join CWLEGAL.tblappealsdatarevisionone a
on a.DATABASEIDNUMBER = s.DBIDNUMBER
left outer join CWLEGAL.individuals i on
i.casenm = a.D_N_NUMBER1 and
i.first_name = a.appellant_first_name and
i.last_name = a.appellant_last_name
where person_id is null
order by orclid21
You are making the first inner join between i and a, the result of which you're joining with s.
Now, if you want to see which records won't join, that's known as anti-join, and in whatever database you're querying it, it may be achieved by either selecting a null result or taking those records as a new result.
Examples, with taking your query (the whole code in the question) as q, assuming you've kept all the needed keys in it:
Example 1:
with your_query as q
select s.orclid21 from q
left join CWLEGAL.tblappealstosupremecourt s
on q.DATABASEIDNUMBER = s.DBIDNUMBER
and s.orclid21 is null
Example 2:
with your_query as q
select s.orclid21 from q
right join CWLEGAL.tblappealstosupremecourt s
on q.DATABASEIDNUMBER != s.DBIDNUMBER
Example 3:
with your_query as q
select s.orclid21 from CWLEGAL.tblappealstosupremecourt s
where s.DBIDNUMBER not in (select distinct q.DATABASEIDNUMBER from q)
I am wanting to change this SQL query to reads several forms not just ![Prices]!
SELECT Option.Index, Option.Desc, Option.Price, Option.Price_ext,
Product.ID, OptionGroup.Option
FROM Product
INNER JOIN (OptionGroup INNER JOIN [Option] ON OptionGroup.ID = Option.OptionGrp)
ON Product.ID = OptionGroup.Product
WHERE (((Product.ID)=[Forms]![Prices]![selName2]) AND ((OptionGroup.Option)="F"))
ORDER BY Option.Index;
Can any one help?
As commented, consider using the IN() operator with comma-separated items inside the WHERE clause which is equivalent to multiple OR statements. And be sure open/close parentheses match as shown below with exaggerated indentation:
SELECT o.[Index], o.Desc, o.Price, o.Price_ext,
p.ID, OptionGroup.Option
FROM Product p
INNER JOIN (OptionGroup INNER JOIN [Option] o ON OptionGroup.ID = o.OptionGrp)
ON p.ID = OptionGroup.Product
WHERE (
(
(p.ID) IN (
[Forms]![Prices]![selName2],
[Forms]![OtherForm1]![FieldName],
[Forms]![OtherForm2]![FieldName],
[Forms]![OtherForm3]![FieldName]
)
)
AND (
(OptionGroup.[Option])='F'
)
)
ORDER BY o.[Index];
Can anybody please help me to write a DB query version of the SQL statement below.
I need a little help around the select statement and the partitioned joins.
I have managed to do this so far.
$query = DB::table(raw('SapakInAdminOrder a'))
->select(raw('a.*'))
->leftJoin(raw('currency cu'), 'a.currency', '=', 'cu.id')
->leftJoin(raw('moodboards m'), 'a.orderMoodboardID', '=', 'm.id')
->join(raw('clients b'), 'a.clientID', '=', 'b.id')
->leftJoin(raw('moodboards mc'), 'b.moodboardID', 'mc.id')
->join(raw('sapakim c'), 'b.sapakID', '=', 'c.id')
->leftJoin(raw('sapakim sm'), 'c.managerid', '=', 'sm.id')
->leftJoin(raw('products p'), 'a.productKey', '=', 'p.id')
->where(function ($query) {
$query->whereNull('a.isDeleted');
$query->orWhere('a.isDeleted', '!=', 1);
});
But I need to achieve this.
select * from (select ROW_NUMBER() OVER(ORDER BY case when (indesign.status=4 or indesign.statusdate is null) then getdate()+2 else indesign.statusdate end ASC) AS RowNum,a.*
FROM sapakInAdminOrder a
left join currency cu on cu.id=a.currency
left join moodboards m on m.id=a.orderMoodboardID
inner join Clients b on a.clientID=b.id
left join moodboards mc on mc.id=b.moodboardID
inner join Sapakim c on b.sapakID=c.id
left join Sapakim sm on sm.id=c.managerid
left join products p on p.id=a.productKey
left join (select * from (select ROW_NUMBER() over(PARTITION BY orderID ORDER BY id DESC) r, * from orderCommunication ) f where r=1) chat on chat.orderId = a.id
left join (select id,[status],orderid,approveSMSDate,coverImage,statusDate from (SELECT id,[status],statusDate,approveSMSDate,coverImage,orderid,ROW_NUMBER() OVER(PARTITION BY orderid ORDER BY id DESC) AS r FROM SapakimInAdminDesigns) f where r=1) indesign on a.id=indesign.orderid
where (a.isDeleted is null or a.isDeleted != 1) and
c.inAdminManagerID=(select id from sapakim where sapakguid='test') and
c.sapakguid='test' and
a.isFreeDesign=0 and
a.transactionID = -1 and
(a.designerPaid is null or a.designerPaid=0) and
(chat.sentToPrinter is null and chat.sentToManager is null and chat.sentToDesigner is null)
) bb where RowNum>=1 and RowNum<31
ORDER BY RowNum asc
I can do the simple ones but couldn't quite really wrap my head around the partitioned joins and the select statement.
I would really appreciate a help on this.
Thanks in advance.
Maybe you should create a database view for these partitioned queries?
Then you can join the view from database afterwards.
Technically these analytical functions are usually not supported by frameworks.
You can use the following package for this purpose.
Features
Converts SQL Queries to Laravel Query Builder.
Assists on building queries as instructed in Laravel Documentation.
Provides options to interact with, for generating different results.
SQL to Laravel Query Builder, A Converter written in PHP
I am also stuck with this type of problem but I got a solution and its working fine for me!
use DB::unprepared() for this type of query :
$path = base_path() . "/storage/agency.sql";
$sql = file_get_contents($path);
DB::unprepared(DB::raw($sql));
All SQL commands in Laravel are prepared by default, but sometimes you need to execute a command in an unprepared mode, because some commands in some database cannot be ran in prepared mode.
Is this what you meant?
$result = DB::Select("select * from (select ROW_NUMBER() OVER(ORDER BY case when (indesign.status=4 or indesign.statusdate is null) then getdate()+2 else indesign.statusdate end ASC) AS RowNum,a.*
FROM sapakInAdminOrder a
left join currency cu on cu.id=a.currency
left join moodboards m on m.id=a.orderMoodboardID
inner join Clients b on a.clientID=b.id
left join moodboards mc on mc.id=b.moodboardID
inner join Sapakim c on b.sapakID=c.id
left join Sapakim sm on sm.id=c.managerid
left join products p on p.id=a.productKey
left join (select * from (select ROW_NUMBER() over(PARTITION BY orderID ORDER BY id DESC) r, * from orderCommunication ) f where r=1) chat on chat.orderId = a.id
left join (select id,[status],orderid,approveSMSDate,coverImage,statusDate from (SELECT id,[status],statusDate,approveSMSDate,coverImage,orderid,ROW_NUMBER() OVER(PARTITION BY orderid ORDER BY id DESC) AS r FROM SapakimInAdminDesigns) f where r=1) indesign on a.id=indesign.orderid
where (a.isDeleted is null or a.isDeleted != 1) and
c.inAdminManagerID=(select id from sapakim where sapakguid='test') and
c.sapakguid='test' and
a.isFreeDesign=0 and
a.transactionID = -1 and
(a.designerPaid is null or a.designerPaid=0) and
(chat.sentToPrinter is null and chat.sentToManager is null and chat.sentToDesigner is null)
) bb where RowNum>=1 and RowNum<31
ORDER BY RowNum asc");
Check out this new Laravel tool called Orator. It lets you simply paste "legacy" SQL and returns Laravel's DB Query Builder syntax.
Laravel Orator News Article
Online Conversion Tool
Assuming you want to display this on the frontend use the relationships wit the eloquent model,
https://laravel.com/docs/master/eloquent-relationships#one-to-one
In the model User there is a One to One relation called identified by the method phone(), if you go to the show view which im assuming passes a $user variable do the following
<?php dd($user->phone); ?>
I might be missing the whole point of the question if you don't mean this.
I have the following Ms Access query that retrieves data successfully:
SELECT stockInventory.purchaseId, stockInventory.itemId, item.itemName, stockInventory.unitId, unit.unitDesc, stockInventory.quantity, stockInventory.costPrice
FROM unit INNER JOIN (item INNER JOIN stockInventory ON item.itemId = stockInventory.itemId) ON unit.unitId = stockInventory.unitId
WHERE (((stockInventory.purchaseId)=1))
Now I want to retrieve these data with row number!
I tried the following:
SELECT A.*, ( SELECT COUNT(*) FROM A WHERE A.itemId>=itemId ) as rowNo
FROM
(
SELECT stockInventory.purchaseId, stockInventory.itemId, item.itemName, stockInventory.unitId, unit.unitDesc, stockInventory.quantity, stockInventory.costPrice
FROM unit INNER JOIN (item INNER JOIN stockInventory ON item.itemId = stockInventory.itemId) ON unit.unitId = stockInventory.unitId
WHERE (((stockInventory.purchaseId)=1))
) AS A;
But it says: The Microsoft access database engine cannot find the input table or query 'A' as the following picture:
How can I solve this problem?
The additional SELECT part
( SELECT COUNT(*) FROM A WHERE A.itemId>=itemId ) as rowNo
is a separate query that doesn't know about A.
I think you must save your original query (= the subquery) as new named query, then you can reference it in both SELECT parts.
SELECT A.*,
( SELECT COUNT(*) FROM mySubquery AS B WHERE B.itemId>=A.itemId ) as rowNo
FROM mySubquery AS A
Now it also gets clearer that you need two instances of the subquery (A and B).
I hope you don't have too many records, because performance will probably be bad. But that wasn't the focus here...
Consider directly adding rowNo subquery in original query:
SELECT (SELECT Count(*) FROM stockInventory AS sub
WHERE sub.itemId <= stockInventory.itemId) AS rowNo,
stockInventory.purchaseId, stockInventory.itemId, item.itemName,
stockInventory.unitId, unit.unitDesc, stockInventory.quantity,
stockInventory.costPrice
FROM unit
INNER JOIN (item
INNER JOIN stockInventory
ON item.itemId = stockInventory.itemId)
ON unit.unitId = stockInventory.unitId
WHERE (((stockInventory.purchaseId)=1))
Each of my clients can have many todo items and every todo item has a due date.
What would be the query for discovering the next undone todo item by due date for each file? In the event that a client has more than one todo, the one with the lowest id is the correct one.
Assuming the following minimal schema:
clients (id, name)
todos (id, client_id, description, timestamp_due, timestamp_completed)
Thank you.
I haven't tested this yet, so you may have to tweak it:
SELECT
TD1.client_id,
TD1.id,
TD1.description,
TD1.timestamp_due
FROM
Todos TD1
LEFT OUTER JOIN Todos TD2 ON
TD2.client_id = TD1.client_id AND
TD2.timestamp_completed IS NULL AND
(
TD2.timestamp_due < TD1.timestamp_due OR
(TD2.timestamp_due = TD1.timestamp_due AND TD2.id < TD1.id)
)
WHERE
TD2.id IS NULL
Instead of trying to sort and aggregate, you're basically answering the question, "Is there any other todo that would come before this one?" (based on your definition of "before"). If not, then this is the one that you want.
This should be valid on most SQL platforms.
This question is the classic pick-a-winner for each group. It gets posted about twice a day.
SELECT *
FROM todos t
WHERE t.timestamp_completed is null
and
(
SELECT top 1 t2.id
FROM todos t2
WHERE t.client_id = t2.client_id
and t2.timestamp_completed is null
--there is no earlier record
and
(t.timestamp_due > t2.timestamp_due
or (t.timestamp_due = t2.timestamp_due and t.id > t2.id)
)
) is null
SELECT c.name, MIN(t.id)
FROM clients c, todos t
WHERE c.id = t.client_id AND t.timestamp_complete IS NULL
GROUP BY c.id
HAVING t.timestamp_due <= MIN(t.timestamp_due)
Avoids a subquery, correlated or otherwise but introduces a bunch of aggregate operations which aren't much better.
Some Jet SQL, I realize it is unlikely that the questioner is using Jet, however the reader may be.
SELECT c.name, t.description, t.timestamp_due
FROM (clients c
INNER JOIN
(SELECT t.client_id, Min(t.id) AS MinOfid
FROM todos t
WHERE t.timestamp_completed Is Null
GROUP BY t.client_id) AS tm
ON c.id = tm.client_id)
INNER JOIN todos t ON tm.MinOfid = t.id
The following should get you close, first get the min time for each client, then lookup the client/todo information
SELECT
C.Id,
C.Name,
T.Id
T.Description,
T.timestamp_due
FROM
{
SELECT
client_id,
MIN(timestamp_due) AS "DueDate"
FROM todos
WHERE timestamp_completed IS NULL
GROUP BY ClientId
} AS MinValues
INNER JOIN Clients C
ON (MinValues.client_id = C.Id)
INNER JOIN todos T
ON (MinValues.client_id = T.client_id
AND MinValues.DueDate = T.timestamp_due)
ORDER BY C.Name
NOTE: Written assuming SQL Server