I'm building a SQL query (Postgres is it matters), that will return me the list of articles with all the fields and with total number of references.
$a = Articles::select(DB::raw('
*,
count(
select * from "references"
where exists (select * from "users" where "users"."reference_id" = "references"."id"
and "article_id" = ?????
) as total'
))->where('created_at', '<', $date)->get();
I simplified it a little bit; there more 'exists' conditions inside the count(); there is also more ->where() rules that are dynamic and hard to rewrite in raw SQL. My main misunderstanding is how to put the corresponding article_id instead of ?????. Could someone give me a hint.
Try this its about binding parameter to Raw query.
https://laracasts.com/discuss/channels/laravel/how-to-bind-parameters-to-a-raw-query?page=1
You may pass in the parameters to be bound to the raw select using a PHP array:
$a = Articles::select(DB::raw('
*,
count(
select * from references r
where exists (select 1 from users u
where u.reference_id = r.id and article_id = ?)
) as total', ['some id here']))
->where('created_at', '<', $date)
->get();
There may be a better way to write your query in Postgres. If you can add some sample data, maybe more can be said about that.
Related
I created a many-to-many relationship between the tables PRODUCT_TYPE and LABEL by creating and intermediate table PRODUCT_TYPE-LABELS. I wanted to retrieve all the products that have the labels 'Gluten free' and 'Lactose free' and found help on a similar subject (How to filter SQL results in a has-many-through relation) but never got it to work properly.
The tables are as follows:
PRODUCT_TYPE{
PRODUCT_TYPE ->Primary Key
CONTAINER
VOLUME_L
PRICE_EUROS
...
}
LABEL{
LABEL_NAME ->Primary Key
REQUIREMENTS
}
PRODUCT_TYPE-LABELS{
PRODUCT_TYPE
LABEL_NAME
}
In fact, even when creating the simplest command
SELECT PRODUCT_TYPE-LABELS.PRODUCT_TYPE
FROM PRODUCT_TYPE-LABELS
I obtain the following error ORA-00933: SQL command not properly ended that I can't solve. I'm working on Apex Oracle (Required for this course).
Thanks !
If your table is really named PRODUCT_TYPE-LABELS then you need to enclose it within double quotes. - is not a standard character that is allowed in table names so to use special characters such as that, you need to put quotes around the table. I would recommend AGAINST using a table name such as that and maybe use something like PRODUCT_TYPE_LABEL.
Does the query work from SQL Developer, SQLPlus or any other tool that you can use to run queries?
Try running the query:
SELECT PRODUCT_TYPE
FROM "PRODUCT_TYPE-LABELS"
select * from (
select rownum rowno, CUST_ID,CUST_NAME,no_of_orders,orders_amount,EMAIL from (
select mst.CUST_ID, mst.CUST_NAME, count(mst.INVONO) no_of_orders, sum(SUB_TOTAL) orders_amount, au.EMAIL
from sales_mst mst,CUSTOMER_INFO cust, APP_USERS au
where cust.USER_NAME = au.USERNAME
and cust.cust_id=mst.cust_id
and (au.gender= :P41_GENDER or :P41_GENDER is null)
and (au.DOB = :P41_DOB or :P41_DOB is null)
group by mst.CUST_ID, mst.CUST_NAME,au.EMAIL
having nvl(sum(SUB_TOTAL),0) > 0
order by 3 desc,4 desc
)) where rowno <=:P41_TO_CUSTOMER
/*select * from (
select rownum rowno, CUST_ID,CUST_NAME,no_of_orders,orders_amount from (
select mst.CUST_ID, mst.CUST_NAME, count(mst.INVONO) no_of_orders, sum(SUB_TOTAL) orders_amount
from sales_mst mst
group by mst.CUST_ID, mst.CUST_NAME
having nvl(sum(SUB_TOTAL),0) > 0
order by 3 desc,4 desc
)) where rowno <=:P41_TO_CUSTOMER
*/
I'm new to Postgres functions.
I'm trying to return part of JSON response similar to:
"ids":[
"9f076580-b5f5-4e73-af08-54d5fc4b87c0",
"bd34cfad-53c7-4443-bf48-280e34d76881"
]
This ids is stored in table unit and I query them as a part of subquery and then transform into JSON with the next query
SELECT coalesce(json_agg(row_to_json(wgc)), '[]'::json)
FROM (
SELECT
(
SELECT COALESCE(json_agg(row_to_json(ids)), '[]'::json)
FROM (SELECT json_agg(l.ids) as "id"
FROM unit
) as ids
) as "ids",
......
FROM companies c
) AS wgc;
The problem is that this query gives me extract object which I want to omit.
"ids":[
{
"id":[
"9f076580-b5f5-4e73-af08-54d5fc4b87c0",
"bd34cfad-53c7-4443-bf48-280e34d76881"
]
}
]
How can omit this "id" object??
It's a bit hard to tell how your table looks like, but something like this should work:
select jsonb_build_object('ids', coalesce(jsonb_agg(id), '[]'::jsonb))
from unit
I think you are overcomplicating things. You only need a single nesting level to get the IDs as an array. There is no need to use row_to_json on the array of IDs. The outer row_to_json() will properly take care of that.
SELECT coalesce(json_agg(row_to_json(wgc)), '[]'::json)
FROM (
SELECT (SELECT json_agg(l.ids) FROM unit ) as ids
....
FROM companies c
) AS wgc;
The fact that the select ... from unit is not a co-related sub-query is a bit suspicious though. This means you will get the same array for each row in the companies table. I would have expected something like (select .. from unit u where u.??? = c.???) as ids
I don't fully understand your question. This code:
SELECT (
SELECT COALESCE(json_agg(row_to_json(ids)), '[]'::json)
FROM (SELECT json_agg(l.ids) as "id"
FROM unit l
) as ids
) as "ids"
Returns:
[{"id":["9f076580-b5f5-4e73-af08-54d5fc4b87c0", "bd34cfad-53c7-4443-bf48-280e34d76881as"]}]
which seems to be what you want.
Here is a db<>fiddle.
Something else in your query is returning a JSON object that has ids as a field. You seem to want to construct the object you want.
I need to query a SQLite database for some entries containing a field the value of which can be one of a defined list: 'Token1', 'Token2', ..., 'TokenN' - potentially a long one.
The straightforward SELECT statement would be something like
SELECT * FROM `my_table` WHERE `token` = 'Token1' OR `token` = 'Token2' OR ...
- far from elegant. I wonder, is there a better way to formulate the statement?
You can use IN Clause
SELECT * FROM `my_table`
WHERE `token` in ('Token1','Token2', 'Token3', ....);
Use the wildcard character %%.
SELECT * FROM `my_table` WHERE `token` like '%Token%'
If your defined list is or can be placed in a table, you can do the following:
SELECT
*
FROM [employeeName] Where dept In (Select dept From #tbl)
I must do this query in another Select in Postgresql :
SELECT COUNT(tn.autoship_box_transaction_id)
FROM memberships.autoship_box_transaction tn
WHERE tn.autoship_box_id = b.autoship_box_id
Do I must use the clause WITH ?
As long as the query produces a single data element, you can use it in place of an attribute:
SELECT (
SELECT COUNT(tn.autoship_box_transaction_id)
FROM memberships.autoship_box_transaction tn
WHERE tn.autoship_box_id = b.autoship_box_id
) AS cnt
, other_column
FROM wherever
;
Have a look at this SQL fiddle demonstrating the use case.
This method often comes with a performance penalty if the db engine actually iterates over the result set and performs the query on each record encountered.
The db engine's optimizer may be smart enough to avoid the extra cost (and it should in the fiddle's toy example), but you have to look at the explain plan to be sure.
Note that its mostly an issue with 'correlated subqueries', ie. queries embedded as shown which depend on the embedding. Your example example appears to be of this kind as you use a table alias b which isn't defined anywhere.
There might be the option of moving the subselect to the from clause (beware: This statement is for explanatory purposes only; you must adapt it to your use case, I am just wild guessing here):
SELECT stats.cnt
, b.other_column
FROM b_table b
JOIN (
SELECT COUNT(tn.autoship_box_transaction_id) cnt
, tn.autoship_box_id
FROM memberships.autoship_box_transaction tn
GROUP BY tn.autoship_box_id
) stats
ON (stats.autoship_box_id = b.autoship_box_id)
;
There are two options. You can either use the with clause, like so:
WITH some_count AS (
SELECT COUNT(tn.autoship_box_transaction_id)
FROM memberships.autoship_box_transaction tn
WHERE tn.autoship_box_id = b.autoship_box_id
)
SELECT * FROM some_count;
Or the second option is to use a sub-query, like so:
SELECT
*
FROM
(
SELECT COUNT(tn.autoship_box_transaction_id)
FROM memberships.autoship_box_transaction tn
WHERE tn.autoship_box_id = b.autoship_box_id
);
Writing a stored procedure that will have multiple input parameters. The parameters may not always have values and could be empty. But since the possibility exists that each parameter may contain values I have to include the criterion that utilizing those parameters in the query.
My query looks something like this:
SELECT DISTINCT COUNT(*) AS SRM
FROM table p
WHERE p.gender IN (SELECT * FROM Fn_SplitParms(#gender)) AND
p.ethnicity IN (SELECT * FROM Fn_SplitParms(#race)) AND
p.marital_status IN (SELECT * FROM Fn_SplitParms(#maritalstatus))
So my problem is if #gender is empty(' ') the query will return data where gender field is empty when I really want to just ignore p.gender all together. I don't want to have to accomplish this task using IF/ELSE conditional statements because they would be too numerous.
Is there any way to use CASE with IN for this scenario? OR
Is there other logic that I'm just not comprehending that will solve this?
Having trouble finding something that works well...
Thanks!
Use or:
SELECT DISTINCT COUNT(*) AS SRM
FROM table p
WHERE
(p.gender IN (SELECT * FROM Fn_SplitParms(#gender)) OR #gender = '')
AND (p.ethnicity IN (SELECT * FROM Fn_SplitParms(#race)) OR #race = '')
AND (p.marital_status IN (SELECT * FROM Fn_SplitParms(#maritalstatus)) OR #maritalstatus = '')
You might also want to consider table-valued parameters (if using SQL Server 2008 and up) - these can sometimes make the code simpler, since they are treated as tables (which in your case, may be empty) and you can join - plus no awkward split function required.