pq: column reference "deleted_at" is ambiguous - sql

I am generating my query dynamically And this is something I have before passing parameters and getting this error pq: column reference "deleted_at" is ambiguous
My query is
SELECT COUNT(*)
FROM issues i
JOIN vehicles v ON (v.id = i.vehicle_id)
WHERE i.asset_owner_id = :asset_owner_id AND deleted_at IS NULL
AND i.added_at >= :from AND i.added_at < :to AND i.status IN (:status)

You have deleted_at in both tables. That is what "ambiguous" means here.
Qualify all column references when you write a query. I don't know which you intend, but something like this:
SELECT COUNT(*)
FROM issues i JOIN
vehicles v
ON v.id = i.vehicle_id
WHERE i.asset_owner_id = :asset_owner_id AND
i.deleted_at IS NULL AND
------^
i.added_at >= :from AND
i.added_at < :to AND
i.status IN (:status);

Related

How to create a case when query to return a result in a table

I have a problem because I have two tables which are joined by country code and return tables with distinct keys. The problem is that I have blanks because these items do not have a country code added, but they have a currency that I would like to use to add items. For example, When "WALUTA" = 'PLN' THEN 'A.CODE =' PL 'but it doesn't work. Is there any other solution?
proc sql;
create table COREP_CR as
select distinct
a.DATA_DANYCH as REPORTING_DATE,
a.CRD_CCF,
b.Kod,
a.EXP_PIERWOTNA as EAD_PRE_CCF,
a.ID,
a.TYPE_ASSET,
a.Currency,
when (TYPE_ASSET) 'Futures' and (Currency) = 'PLN' then a.KOD = 'PLN'
end,
I got >ERROR 76-322: Syntax error, statement will be ignored.
>
from corep as a
left join _work.country_corep as b on a.Kraj=b.Kraj
Group by b.Kod, a.TYPE_ASSET, a.CRD_CCF, ORIGINAL_ASSET_CLASS, FINAL_ASSET_CLASS, PRODUCT_TYPE
;
QUIT;
After helped i got like this new colum _TEMP but i would like put this result to columdn Kod.
The case statement should look like this:
case when a.TYPE_ASSET = 'Futures' and a.Currency = 'PLN' then 'PLN'
else b.KOD
end "KOD"
So when criteria defined are met, the now 'virtual' field named "KOD" will be returned as "PLN", otherwise the contents of the field KOD from the joind table _work.country_corep will be returned.
If i understand correctly what you are trying to do - if there is not a row corresponding in the joined table b, put something else in the field which is otherwise filled from data from this table, then your select should look like this:
select distinct
a.DATA_DANYCH as REPORTING_DATE,
a.CRD_CCF,
--b.Kod,
Case When a.TYPE_ASSET='Futures' And a.Currency='PLN' Then 'PLN' --IF criteria are met, let us returned PLN as Kod
Else b.KOD --OTHERWISE return the Kod from table b
End "Kod",
a.EXP_PIERWOTNA as EAD_PRE_CCF,
a.ID,
a.TYPE_ASSET,
a.Currency
from corep as a
left join _work.country_corep as b on a.Kraj=b.Kraj
Group by b.Kod, a.TYPE_ASSET, a.CRD_CCF, ORIGINAL_ASSET_CLASS, FINAL_ASSET_CLASS, PRODUCT_TYPE
;

Is it possible to have multiple CASE in a GROUP BY that can make it so it doesn't group at all?

I'm trying to query come datas and on a spcific case I might have to group datas by multiple values. But most of the time it needs not to be grouped at all. So I'm using multiple CASE WHEN {...} inside the GROUP BY, and all the WHEN basically have the same condition. The problem is that if the condition is met, everything works fine. But if it's false, then the GROUP BY section is empty and the query returns only the first row.
I basically tried to reorganize the quesry in every way that came to my mind, nothing seemed to work, and I didn't find anything conclusive on internet.
I'm using MySql 5.7.
SELECT
{element I want to select}
FROM
{tables}
WHERE
{conditions}
GROUP BY
CASE WHEN (condition) THEN [table].[column] END,
CASE WHEN (condition) THEN [table].[column] END,
CASE WHEN (condition) THEN [table].[column] END
ORDER BY
{...}
Full query :
SELECT
tx.code,
IFNULL(hr.label,'') AS rh_label,
IFNULL(cli.label,'') AS client_label,
DATE(FROM_UNIXTIME(created.value / 1000)) AS Created,
IFNULL(item_enfant.label,'') As Parasite,
IFNULL(item_parent.label,'') As Zone,
CASE
WHEN :perWeek = 'week' THEN SUM(qte.value)
ELSE qte.value
END AS Quantite,
CEILING(DATEDIFF(DATE(FROM_UNIXTIME(created.value / 1000)), DATE(FROM_UNIXTIME(:from / 1000))) / 7) AS Weeks
FROM tx
LEFT JOIN tx_type AS tt ON tt.id = tx.tx_type_id
LEFT JOIN human_resource AS hr ON hr.id = tx.human_resource_id
LEFT JOIN client AS cli ON cli.id = tx.client_id
LEFT JOIN tx_state AS ts ON ts.id = tx.current_tx_state_id
LEFT JOIN workflow_step AS ws ON ws.id = ts.workflow_step_id
LEFT JOIN item AS item_enfant ON item_enfant.item_list_id = tx.item_list_id
JOIN item_type AS ite ON ite.id = item_enfant.item_type_id
LEFT JOIN item_meta AS qte ON qte.item_id = item_enfant.id AND qte.name = 'qtePourRapport'
LEFT JOIN item_prop AS created ON created.item_id = item_enfant.id AND created.name = 'visite.timestamp'
JOIN item AS item_parent ON item_parent.id = item_enfant.parent_item_id
JOIN item_type AS itp ON itp.id = item_parent.item_type_id
WHERE
ite.name = 'parasite' AND
item_enfant.product_id IN (:parasiteIds) AND
itp.name = 'zone' AND
item_parent.product_id IN (:zoneIds) AND
cli.id = (:clientId) AND
ws.logic_id = 600 AND
created.value BETWEEN :from AND :to AND
created.value IS NOT NULL AND qte.value IS NOT NULL
GROUP BY
CASE WHEN :perWeek = 'week' THEN item_enfant.label END, #Parasite
CASE WHEN :perWeek = 'week' THEN item_parent.label END, #Zone
CASE WHEN :perWeek = 'week' THEN CEILING(DATEDIFF(DATE(FROM_UNIXTIME(created.value / 1000)), DATE(FROM_UNIXTIME(:from / 1000))) / 7) END #Weeks
ORDER BY
Created;
I'm getting the datas of the first row alone. And I actually have no idea how to get it just not to group if the condition is not met.
You need a unique value for the aggregation or two separate queries. The simplest method might be union all:
select . . .
from t
where <conditions not to group by>
union all
select . . .
from t
where <conditions to group by>
group by . . .;
You need to be sure that each subquery returns compatible columns.
SELECT
{element I want to select}
FROM
{tables}
WHERE
{conditions}
GROUP BY
CASE WHEN (condition) THEN [table].[column] ELSE [some unique value of same data-type as column] END,
CASE WHEN (condition) THEN [table].[column] ELSE [some unique value of same data-type as column] END,
CASE WHEN (condition) THEN [table].[column] ELSE [some unique value of same data-type as column] END
ORDER BY
{...}
I guess the missing ELSE clause will evaluate to NULL. This is constant, thus all rows will be in the same group, thus there will be only one row returned for this group. To avoid grouping you need unique values over all returned rows in the combination of the grouping-elements (not in every single grouping-element as stated erlier).
EDIT
Thus the soultion from the comment might be easier: Just add another grouping-element CASE WHEN !(condition) THEN CONCAT([different elements making it unique]) END

Raw SQL statement invalid

If this query would be done in Rails ORM, it would look like
ids = User.find(user_id).conversations.pluck(:id)
UserMessage.where("'conversation'.'id' IN (?)", ids)
My models are:
class User
has_many :conversations, through: :user_conversations
end
class UserMessage
belongs_to :user
belongs_to :conversation
end
In raw SQL:
ActiveRecord::Base.connection.execute(
%( SELECT "user_messages".*,
( SELECT array_agg(t)
FROM (
SELECT "conversations"."id"
FROM "conversations"
INNER JOIN "users_conversations" ON "conversations"."id" = "users_conversations"."conversation_id"
WHERE "users_conversations"."user_id" = 'f044e064-0b6f-4371-91aa-3c03e31c8ad8'
) t
) AS this_user_conversations
FROM "user_messages"
WHERE "user_messages"."conversation_id" IN (this_user_conversations)))
this gives
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "this_user_conversations" does not exist
LINE 11: WHERE "user_messages"."conversation_id" IN (this_user_conver...
But well as far as I understand, this query defines this value with AS statement.
The where clause happens before the select list so it can't see the subquery. An alternative:
select
um.*, tuc.this_user_conversations
from
"user_messages" um
inner join
(
select array_agg(c."id") as this_user_conversations
from
"conversations" c
inner join
"users_conversations" uc on c."id" = uc."conversation_id"
where uc."user_id" = 'f044e064-0b6f-4371-91aa-3c03e31c8ad8'
) tuc on um."conversation_id" = any (tuc.this_user_conversations)

Where clause no longer working in Rails 3.2.3?

I upgraded to Rails 3.2.3 and all of a sudden this code no longer works:
def self.search(query, project_id, person_id)
if query
where("number LIKE ?", "%#{query}%")
elsif project_id
where("project_id LIKE ?", project_id)
elsif person_id
where("projects.person_id = ?", person_id)
else
scoped
end
end
It is the last where clause that triggers the error:
SQLite3::SQLException: no such column: projects.person_id: SELECT COUNT(DISTINCT "invoices"."id") FROM "invoices" LEFT OUTER JOIN "items" ON "items"."invoice_id" = "invoices"."id" LEFT OUTER JOIN "payments" ON "payments"."invoice_id" = "invoices"."id" WHERE "invoices"."user_id" = 1 AND (projects.person_id = '1')
In my models all the belongs_to and has_many statements are set correctly and it worked in my previous version of Rails (not sure which one that was though).
Can anybody tell me how to get this working again?
Thanks for any help.
I believe you'll have to join the projects table:
..
elsif person_id
joins(:projects).where("projects.person_id = ?", person_id)
else
..

Oracle SQL merge statement with only 1 table and a bunch of values

I'm using Spring JDBC and oracle SQL.
using the SpringJDBC class MapSqlParameterSource, i have mapped the data i want to merge.
Now i want to use the merge statement to update/insert database table. All i have is one table and a bunch of parameters i want to merge into it.
merge into proj.person_registry pr
using ( ! parameters should go here somehow? )
on (pr.id = :id or pr.code = :code)
when matched then
update set pr.code = :code,
pr.name = :name,
pr.firstname = :firstname,
pr.cl_gender = :cl_gender,
pr.cl_status = :cl_status,
pr.aadress = :aadress,
pr.aadress_date = :aadress_date
when not matched then
insert values (:code, :name, :firstname, :cl_gender, :cl_status, ;aadress, :aadress_date);
Do i have to somehow create a temporary table for the using keyword or is there another way? how would i go about merging like this?
also there are two unique keys pr.id and pr.code. Sometimes the parameter :id is null, when this happens I want to reach the update statement based on pr.code getting matched to :code. Will it still work if my update contains the line:
update set pr.code = :code,
This should work:
merge into proj.person_registry pr
using (
select 42 as id
'xyz' as code,
'Dent' as name,
'Arthur' as firstname,
'male' as cl_gender
'closed' as cl_status,
'Somewher' as aaddress,
current_date as aaddress_date
from dual
) t on (pr.id = t.id or pr.code = t.code)
when matched then
update set pr.code = t.code,
pr.name = t.name,
pr.firstname = t.firstname,
pr.cl_gender = t.cl_gender,
pr.cl_status = t.cl_status,
pr.aadress = t.aadress,
pr.aadress_date = t.aadress_date
when not matched then
insert values (t.code, t.name, t.firstname, t.cl_gender, t.cl_status, ;aadress, t.aadress_date);
I'm not familiar with Spring's JDBC template, but replacing the actual values in the select ... from dual query by parameter placeholders should work.