【发布时间】:2018-01-09 20:40:08
【问题描述】:
我有一个 SQL 查询,它使用 PostgreSQL WITH AS 充当 XOR 或“非”左连接。目标是返回两个查询之间唯一的内容。
在这种情况下,我想知道哪些用户在某个时间段内有交易,而在另一个时间段内没有交易。 SQL 查询通过使用WITH 选择new_transactions 中某个日期范围的所有事务,然后选择older_transactions 中另一个日期范围的所有事务来执行此操作。从这些中,我们将从new_transactions 中选择older_transactions 中的NOT。
我在 SQL 中的查询是:
/* New Customers */
WITH new_transactions AS (
select * from transactions
where merchant_id = 1 and inserted_at > date '2017-11-01'
), older_transactions AS (
select * from transactions
where merchant_id = 1 and inserted_at < date '2017-11-01'
)
SELECT * from new_transactions
WHERE user_id NOT IN (select user_id from older_transactions);
我正在尝试通过子查询在 Ecto 中复制它。我知道我不能在where: 语句中使用subquery,这会留下left_join。如何在 Elixir/Ecto 中复制它?
我在 Elixir/Ecto 中复制的内容抛出了 (Protocol.UndefinedError) protocol Ecto.Queryable not implemented for [%Transaction....
灵药/Ecto代码:
def new_merchant_transactions_query(merchant_id, date) do
from t in MyRewards.Transaction,
where: t.merchant_id == ^merchant_id and fragment("?::date", t.inserted_at) >= ^date
end
def older_merchant_transactions_query(merchant_id, date) do
from t in MyRewards.Transaction,
where: t.merchant_id == ^merchant_id and fragment("?::date", t.inserted_at) <= ^date
end
def new_customers(merchant_id, date) do
from t in subquery(new_merchant_transactions_query(merchant_id, date)),
left_join: ot in subquery(older_merchant_transactions_query(merchant_id, date)),
on: t.user_id == ot.user_id,
where: t.user_id != ot.user_id,
select: t.id
end
更新:
我尝试将其更改为where: is_nil(ot.user_id),,但得到了同样的错误。
【问题讨论】:
-
LEFT JOIN <some_table> ON <related_keys> WHERE <some_table.column> IS NULL。不过,我不知道该怎么写。请注意,您当前的最终WHERE似乎是将您的LEFT OUTER JOIN变成(常规)INNER JOIN的条件。 -
我尝试将其更改为
where: is_nil(ot.user_id),并得到相同的错误。可能是别的东西 -
请包含完整的错误,看起来好像已经从 Repo 中读取了交易列表??
-
请附上要点中使用的
new_merchant_transactions代码的来源。
标签: sql elixir common-table-expression ecto