I have a list of contracts like this query:
select
r.vnum, r.BEITRAGSGR
from
ufrisk r
inner join
ufvert v on r.vnum = v.vnum
inner join
allgvert a on a.vnum = r.vnum
where
a.version = r.version
How can I search for all contracts that have more than one (different) value in the column r.BEITRAGSGR?
Assuming vnum is a "contract", you can use aggregation:
select vnum
from ufrisk
group by vnum
having min(BEITRAGSGR) <> max(BEITRAGSGR);
If you want the original rows, use exists:
select u.*
from ufrisk u
where exists (select 1
from ufrisk u2
where u2.vnum = u.vnum and u2.BEITRAGSGR <> u.BEITRAGSGR
);
Related
I am trying to run my query but I get an error.
This is my query:
if exists (select CODE_ISIN
from cte
where code_ISIN not in (select [STATUT_TITRE], [CODE_ISIN]
from TT_TITRE A
inner join TT_STATUT_TITRE B on A.TITRE_ID = B.TITRE_ID))
begin
select 'ko'
end
begin
select 'ok'
end
Remove [STATUT_TITRE] from sub-query as it will accept only one expression :
select c.CODE_ISIN
from cte c
where code_ISIN not in (select [CODE_ISIN] -- only one expression needed
from TT_TITRE A inner join
TT_STATUT_TITRE B
on A.TITRE_ID = B.TITRE_ID
);
I would suggest to use NOT EXISTS instead :
where not exists (select 1
from TT_TITRE A inner join
TT_STATUT_TITRE B
on A.TITRE_ID=B.TITRE_ID
where CODE_ISIN = c.CODE_ISIN
);
select *
from EFLOVRelationship R
where R.parentEFLOVValueId = '5320'
and R.childEFLOVId in (select Eflovid
from EFFieldLOVStaticValue
where efLovId = 49)
In the above query I want to fetch 2 columns from EFFieldLOVStaticValue table and display.
Thanks in advance
Use Inner Join
SELECT R.*,
V.field1,
V.field2
FROM eflovrelationship R
INNER JOIN effieldlovstaticvalue V
ON R.childeflovid = V.eflovid
WHERE R.parenteflovvalueid = '5320'
AND V.eflovid = 49
If your table has 1:N relationship then use Distinct to avoid duplicates in result
If you want just one record from effieldlovstaticvalue table for each R.childeflovid column then use Cross Apply but you need to use required column to order the result and choose the top 1 record
SELECT R.*,
CS.field1,
CS.field2
FROM eflovrelationship R
CROSS apply (SELECT TOP 1 field1,
field2
FROM effieldlovstaticvalue V
WHERE R.childeflovid = V.eflovid
AND eflovid = 49
ORDER BY someordercolumn) CS
WHERE R.parenteflovvalueid = '5320'
Use join:
select R.*, sv.?, sv.?
from EFLOVRelationship R join
EFFieldLOVStaticValue sv
ON sv.Eflovid = R.childEFLOVId and sv.efLovId = 49
where R.parentEFLOVValueId = '5320'
I have a rather complex query that orders the results based on a sub-query. This works fine. The query is below.
SELECT enrollments.*, users.*
FROM enrollments
INNER JOIN users
ON enrollments.user_id = users.id
WHERE enrollments.preview = FALSE
ORDER BY (
SELECT COUNT(progress_tracker)
FROM progress_tracker
WHERE progress_tracker.enrollment_id = enrollments.id
AND progress_tracker.completed = TRUE
)
Here I'm selecting the fields from the User and Enrollment table. I ideally want one more field in the sql results. This field represents the results from the ORDER BY sql:
SELECT COUNT(progress_tracker)
FROM progress_tracker
WHERE progress_tracker.enrollment_id = enrollments.id
AND progress_tracker.completed = TRUE
Is it possible to create a field from this query and append it to the results for each row? The name of the row would be appropriately termed as enrollment_progress_tracker_completed_count. If so, how can I do this?
Add the subquery to the select and then use it for ordering:
SELECT e.*, u.*,
(SELECT COUNT(*)
FROM progress_tracker pt
WHERE pt.enrollment_id = e.id AND pt.completed = TRUE
) as newcol
FROM enrollments e INNER JOIN
users u
ON e.user_id = u.id
WHERE e.preview = FALSE
ORDER BY newcol;
Use a temporary table
with tempCounts as(
SELECT enrollment_id, COUNT(progress_tracker) as countValue
FROM progress_tracker
WHERE progress_tracker.completed = TRUE
group by enrollment_id)
SELECT enrollments.*, users.*,tempCounts.countValue
FROM enrollments, users.*,tempCounts
INNER JOIN users
ON enrollments.user_id = users.id
WHERE enrollments.preview = FALSE
and enrollments.id = tempCounts.enrollment_id
ORDER BY tempCounts.countValue
I have the following query which returns the desired data. What I want to do is delete that data, however when I change the Select DQ.* to DELETE FROM DQ, I get an error indicating that
'... not updatable because the modification affects multiple base table'
I need to delete entries from the tbaccess_groupPermission table where appropriate module records are not found in the tbaccess_companyModules table.
WITH DQ AS
(
SELECT GP.* FROM tbaccess_groupPermission GP
JOIN tbaccess_groups G ON GP.GroupID = G.ID
WHERE G.CompanyID=6
AND GP.RoleName NOT IN
(
select Distinct(R.RoleName)
FROM tbAccess_Roles R
INNER JOIN tbAccess_CompanyModules C on R.ModuleID = C.ModuleID
WHERE C.CompanyID = 6)
)
SELECT * FROM DQ
Why not change the WITH statement to use an IN clause?
Something like
WITH DQ AS
(
SELECT GP.* FROM tbaccess_groupPermission GP
WHERE GP.GroupID IN (SELECT G.ID FROM tbaccess_groups G WHERE G.CompanyID=6)
AND GP.RoleName NOT IN
(
select Distinct(R.RoleName)
FROM tbAccess_Roles R
INNER JOIN tbAccess_CompanyModules C on R.ModuleID = C.ModuleID
WHERE C.CompanyID = 6)
)
I have the following query:
SELECT sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount, 'rma' as
"creditType", "Clients"."company" as "client", "Clients".id as "ClientId", "Rmas".*
FROM "Rmas" JOIN "EsnsRmas" on("EsnsRmas"."RmaId" = "Rmas"."id")
JOIN "Esns" on ("Esns".id = "EsnsRmas"."EsnId")
JOIN "EsnsSalesOrderItems" on("EsnsSalesOrderItems"."EsnId" = "Esns"."id" )
JOIN "SalesOrderItems" on("SalesOrderItems"."id" = "EsnsSalesOrderItems"."SalesOrderItemId")
JOIN "Clients" on("Clients"."id" = "Rmas"."ClientId" )
WHERE "Rmas"."credited"=false AND "Rmas"."verifyStatus" IS NOT null
GROUP BY "Clients".id, "Rmas".id;
The problem is that the table "EsnsSalesOrderItems" can have the same EsnId in different entries. I want to restrict the query to only pull the last entry in "EsnsSalesOrderItems" that has the same "EsnId".
By "last" entry I mean the following:
The one that appears last in the table "EsnsSalesOrderItems". So for example if "EsnsSalesOrderItems" has two entries with "EsnId" = 6 and "createdAt" = '2012-06-19' and '2012-07-19' respectively it should only give me the entry from '2012-07-19'.
SELECT (count(*) * sum(s."price")) AS amount
, 'rma' AS "creditType"
, c."company" AS "client"
, c.id AS "ClientId"
, r.*
FROM "Rmas" r
JOIN "EsnsRmas" er ON er."RmaId" = r."id"
JOIN "Esns" e ON e.id = er."EsnId"
JOIN (
SELECT DISTINCT ON ("EsnId") *
FROM "EsnsSalesOrderItems"
ORDER BY "EsnId", "createdAt" DESC
) es ON es."EsnId" = e."id"
JOIN "SalesOrderItems" s ON s."id" = es."SalesOrderItemId"
JOIN "Clients" c ON c."id" = r."ClientId"
WHERE r."credited" = FALSE
AND r."verifyStatus" IS NOT NULL
GROUP BY c.id, r.id;
Your query in the question has an illegal aggregate over another aggregate:
sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount
Simplified and converted to legal syntax:
(count(*) * sum(s."price")) AS amount
But do you really want to multiply with the count per group?
I retrieve the the single row per group in "EsnsSalesOrderItems" with DISTINCT ON. Detailed explanation:
Select first row in each GROUP BY group?
I also added table aliases and formatting to make the query easier to parse for human eyes. If you could avoid camel case you could get rid of all the double quotes clouding the view.
Something like:
join (
select "EsnId",
row_number() over (partition by "EsnId" order by "createdAt" desc) as rn
from "EsnsSalesOrderItems"
) t ON t."EsnId" = "Esns"."id" and rn = 1
this will select the latest "EsnId" from "EsnsSalesOrderItems" based on the column creation_date. As you didn't post the structure of your tables, I had to "invent" a column name. You can use any column that allows you to define an order on the rows that suits you.
But remember the concept of the "last row" is only valid if you specifiy an order or the rows. A table as such is not ordered, nor is the result of a query unless you specify an order by
Necromancing because the answers are outdated.
Take advantage of the LATERAL keyword introduced in PG 9.3
left | right | inner JOIN LATERAL
I'll explain with an example:
Assuming you have a table "Contacts".
Now contacts have organisational units.
They can have one OU at a point in time, but N OUs at N points in time.
Now, if you have to query contacts and OU in a time period (not a reporting date, but a date range), you could N-fold increase the record count if you just did a left join.
So, to display the OU, you need to just join the first OU for each contact (where what shall be first is an arbitrary criterion - when taking the last value, for example, that is just another way of saying the first value when sorted by descending date order).
In SQL-server, you would use cross-apply (or rather OUTER APPLY since we need a left join), which will invoke a table-valued function on each row it has to join.
SELECT * FROM T_Contacts
--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989
-- CROSS APPLY -- = INNER JOIN
OUTER APPLY -- = LEFT JOIN
(
SELECT TOP 1
--MAP_CTCOU_UID
MAP_CTCOU_CT_UID
,MAP_CTCOU_COU_UID
,MAP_CTCOU_DateFrom
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(#in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(#in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
) AS FirstOE
In PostgreSQL, starting from version 9.3, you can do that, too - just use the LATERAL keyword to achieve the same:
SELECT * FROM T_Contacts
--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989
LEFT JOIN LATERAL
(
SELECT
--MAP_CTCOU_UID
MAP_CTCOU_CT_UID
,MAP_CTCOU_COU_UID
,MAP_CTCOU_DateFrom
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(__in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(__in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
LIMIT 1
) AS FirstOE
Try using a subquery in your ON clause. An abstract example:
SELECT
*
FROM table1
JOIN table2 ON table2.id = (
SELECT id FROM table2 WHERE table2.table1_id = table1.id LIMIT 1
)
WHERE
...