Return in just one lines - postgresql

I have a problem, I have a query in postgresql and I need to do a SUM, however, it returns me a total of 4 lines because the ids of my routes are different, and I need to add the "totalChecklists" and return the amount of all in one line.
select "users"."id",
count((cycles.adherence >= 100 and cycles.justified = false) or null) as "routesDone",
count((cycles.adherence < 100 and cycles.opened = false) or null) as "routesNotDone",
count((cycles.opened = true and cycles.adherence < 100) or null) as "routesOpened",
count(cycles.justified or null) as "routesJustified",
routes."totalSpots" AS "totalCheck",
count(cycles.id) as "routesOnPeriod",
(
count((cycles.adherence >= 100 and cycles.justified = false) or null) +
count((cycles.adherence < 100 and cycles.opened = false) or null) +
count((cycles.opened = true and cycles.adherence < 100) or null) +
count(cycles.justified or null)
) as "routesTotal",
0 as "routesDoneLate",
0 as "routesLate",
SUM(case when cycles.adherence >= 100 then routes."totalAssets" else 0 end) AS "coveredAssets",
SUM(case when cycles.adherence < 100 then routes."totalAssets" else 0 end) AS "uncoveredAssets"
from "routes"
inner join "cycles" on "routes"."identifier" = "cycles"."routeIdentifier"
inner join "workspaces" on "cycles"."workspaceId" = "workspaces"."id"
inner join "users" on "users"."id" = "cycles"."inspectorId"
where "routes"."deleted_at" is null
and "cycles"."deletedAt" is null
and "workspaces"."deleted" = false
and "cycleStartAt" <= '2022-07-11T02:59:59Z'
and "cycleEndAt" >= '2022-04-12T03:00:00Z'
and "users"."id" = 'b67830a7-39fc-4ad5-bf26-07a43dcd3676'
and "routes"."contextPath" like '/malicious-interaction-murder-32%'
and "routes"."deleted_at" is null
group by
users.id,
routes.id
My return:
Sorry for my bad english, I hope I managed to be very clear.
Thank you very much in advance

Related

Linq Limit/Group by Id when joining IQueryables

I have a list of ids, that I then have multiple IQueryables that at the end I am joining to return my results. However some of these queries could have multiple records for that particular ID and I only need 1 record per ID from my set of x IDs. For example there could be 1 Name record, 3 Addresses, 2 Emails, 4 Phones for a single ID, but I only need 1 of each, does not matter which if multiple exist.
var clientNames = (
from n in db.Names
join cnl in db.ClientNameLinks on n.name_id equals cnl.name_id
where request.Ids.Contains(cnl.client_id)
&& n.name_id > 0
&& n.nametype_id != null
select new
{
n.display_name,
cnl.client_id
});
var clientAddresses = (
from a in db.Addresses
join cal in db.ClientAddressLinks on a.address_id equals cal.address_id
where request.Ids.Contains(cal.client_id)
&& a.address_id > 0
select new {
a.display_address,
cal.client_id
});
var clientEmails = (
from e in db.Emails
join cel in db.ClientEmailLinks on e.email_id equals cel.email_id
where request.Ids.Contains(cel.client_id)
&& e.email_id > 0
select new {
e.email_address,
cel.client_id
});
var clientPhones = (
from p in db.Phones
join cpl in db.ClientPhoneLinks on p.phone_id equals cpl.phone_id
where request.Ids.Contains(cpl.client_id)
&& p.phone_id > 0
select new {
p.phone_num,
cpl.client_id
});
var rows = await (
from n in clientNames
join a in clientAddresses on n.client_id equals a.client_id into n_a
from na in n_a.DefaultIfEmpty() //LEFT JOIN
join e in clientEmails on n.client_id equals e.client_id into n_e
from ne in n_e.DefaultIfEmpty() //LEFT JOIN
join ph in clientPhones on n.client_id equals ph.client_id into n_p
from np in n_p.DefaultIfEmpty() //LEFT JOIN
select new PiiDiamondClient
{
ClientId = n.client_id,
DisplayName = n.display_name,
DisplayAddress = na.display_address,
EmailAddress = ne.email_address,
PhoneExtension = np.phone_ext,
PhoneNumber = np.phone_num
}).Distinct().ToListAsync();
return rows.OrderBy(x => x.ClientId).ToList();
Your last query can be rewritten in the following way. It will exactly get one record from JOIN which can multiply result set.
var query =
from n in clientNames
from a in clientAddresses.Where(a => n.client_id == a.client_id)
.Take(1).DefaultIfEmpty() //OUTER APPLY or LEFT JOIN on ROW_NUMBER query
from e in clientEmails.Where(e => n.client_id == e.client_id)
.Take(1).DefaultIfEmpty() //OUTER APPLY or LEFT JOIN on ROW_NUMBER query
from ph in clientPhones.Where(ph => n.client_id == ph.client_id)
.Take(1).DefaultIfEmpty() //OUTER APPLY or LEFT JOIN on ROW_NUMBER query
select new PiiDiamondClient
{
ClientId = n.client_id,
DisplayName = n.display_name,
DisplayAddress = a.display_address,
EmailAddress = e.email_address,
PhoneExtension = ph.phone_ext,
PhoneNumber = ph.phone_num
};

append subquery based on case- postgresql

My table is crash
id
jurisdiction
drugs_inv
alcohol_inv
dr_sex
severity_id
1
NT
true
false
Male
3
2
NSW
false
false
Male
3
3
WA
true
true
Female
3
4
WA
true
true
Male
4
I want to have a subquery based on t_factors array
if it has 1 then filter where alcohol_inv = true
if it has 2 then filter where drugs_inv = true
if both 1 and 2 then use both above conditions
something like may be append a subquery...within the query in the following spaces..
[subqry for alcohol_inv = true]
[subqry for drugs_inv = true]
how to go about it?
My query:
WITH myvars(t_state,
t_factors,
) AS(values(
'WA',
'{1,2}', --factors
))
SELECT
dr_sex,
COUNT(*) as all_crashes,
COUNT(t1.id) filter (WHERE severity_id >= 3) as fsi_crashes,
COUNT(t1.id) filter (WHERE severity_id = 3) as si_crashes,
COUNT(t1.id) filter (WHERE severity_id = 4) as fatal_crashes
FROM
crash t1
,myvars
WHERE
(jurisdiction = t_state OR t_state is null)
AND (( CASE
WHEN 1 = ANY (t_factors) THEN '[subqry for alcohol_inv = true]'
WHEN 2 = ANY (t_factors) THEN '[subqry for drugs_inv = true]'
END) factor
OR
t_factors is null)
AND severity_id > 1
AND dr_sex = ANY( '{Male, Female}'::text[] )
GROUP BY dr_sex
Since alcohol_inv is boolean then [subqry for alcohol_inv = true] is simply alcohol_inv. Maybe this query will do the job then
WITH myvars(t_state, t_factors) AS
(
values ('WA', '{1,2}'::integer[])
)
SELECT
dr_sex,
COUNT(*) as all_crashes,
COUNT(t1.id) filter (WHERE severity_id >= 3) as fsi_crashes,
COUNT(t1.id) filter (WHERE severity_id = 3) as si_crashes,
COUNT(t1.id) filter (WHERE severity_id = 4) as fatal_crashes
FROM
crash t1, myvars
WHERE
(jurisdiction = t_state OR t_state is null)
AND
(
CASE WHEN 1 = ANY(t_factors) THEN alcohol_inv
WHEN 2 = ANY(t_factors) THEN drugs_inv END
OR t_factors is null
)
AND severity_id > 1
AND dr_sex in ('Male', 'Female')
GROUP BY dr_sex;

Update To 0 when Count Is 0 Not Display Null

I am running this update query, and I was hoping it would update the table to hold a value of 0 instead of displaying NULL when the count is 0. How can this be updated to force the table so show a 0 when the count returned is 0?
set #sql =
'UPDATE cra
SET mastercounts = te.LC
FROM #tbl_test As cra
JOIN (
select
,COUNT(CASE WHEN recordID < 1 THEN 0 ELSE recordID end) As LC
,employeename
from productioninformaiton
where salestatus = (''Approved'', ''Shipped'')
Group By employeename
) As te
ON cra.[StoreName] = te.[StoreName]
AND cra.[employeename] = te.[employeename]'
Exec (#sql)
Maybe the field "recordID" is returning NULL in some cases, which makes COUNT(NULL) return NULL as well. Try replacing
COUNT(CASE WHEN recordID < 1 THEN 0 ELSE recordID end) As LC
with
COUNT(CASE WHEN ISNULL(recordID, 0) < 1 THEN 0 ELSE ISNULL(recordID, 0) end) As LC

LINQ to Entities: Convert SQL Sub Select

I got this figured out.
No need to answer.
The system says I have to wait 8 hours before answering my own questions. But for now the answer is below:
Here is the answer:
var startDate = DateTime.Today.AddDays(-30);
var results = (from h in Histories
join q in Quotes
on h.QuoteID equals q.QuoteID
join a in Agencies
on q.AgencyID equals a.AgencyID
where q.Status == "Inforce" &&
q.LOB == "Vacant" &&
q.EffectiveDate > startDate &&
h.Deleted == null &&
h.DeprecatedBy == null &&
h.TransactionStatus == "Committed" &&
a.DC_PLT_Roles.Any(r => r.Name == "Wholesaler")
group new {h} by new {h.PolicyNumber} into g
select new {
MaxHistoryID = g.Max (x => x.h.HistoryID),
comment = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.Comment).FirstOrDefault()
}).ToList();
The key code was:
comment = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.Comment).FirstOrDefault()
We are in the process of converting SQL / Stored Procedures to LINQ to Entities statements. And I can’t figure out the proper syntax for a sub select.
Currently I am converting this SQL:
declare #startDate DateTime
set #startDate = DATEADD(DD, -30, GETDATE())
select * from history where historyid in(
select MAX(h.historyid) as HistoryId
from History h (nolock)
inner join Quote q (nolock) on h.QuoteID = q.QuoteID
inner join Agency (nolock) a on q.AgencyID = a.AgencyID
inner join DC_PLT_EntityRoles er (nolock) on a.AgencyID = er.EntityID
inner join DC_PLT_Roles (nolock) r on er.RoleID = r.RoleID
where
q.Status = 'Inforce'
and q.LOB = 'Vacant'
and q.EffectiveDate > #startDate
and h.Deleted is null --
and h.DeprecatedBy is null --
and h.TransactionStatus = 'Committed'
and r.Name = 'Wholesaler'
group by h.PolicyNumber)
As you can see the code above is made up of two select statements. The main select (select * from history).. And a filter select (select MAX(h.historyid)…)
I got the filter select working (See below):
var startDate = DateTime.Today.AddDays(-30);
var results = (from h in Histories
join q in Quotes
on h.QuoteID equals q.QuoteID
join a in Agencies
on q.AgencyID equals a.AgencyID
where q.Status == "Inforce" &&
q.LOB == "Vacant" &&
q.EffectiveDate > startDate &&
h.Deleted == null &&
h.DeprecatedBy == null &&
h.TransactionStatus == "Committed" &&
a.DC_PLT_Roles.Any(r => r.Name == "Wholesaler")
group new {h} by new {h.PolicyNumber} into g
select new {
MaxHistoryID = g.Max (x => x.h.HistoryID)
}).ToList();
However I can’t figure out the proper syntax to set up the main select. (Basically getting the records from the History table using the HistoryID from the filter select.)
Any help would be appreciated.
Thanks for your help.
I figured it out, here is the code:
var startDate = DateTime.Today.AddDays(-30);
var results = (from h in Histories
.Include("Quote")
.Include("Quote.Agency")
where h.Quote.Status == "Inforce" &&
h.Quote.LOB == "Vacant" &&
h.Quote.EffectiveDate > startDate &&
h.Deleted == null &&
h.DeprecatedBy == null &&
h.TransactionStatus == "Committed" &&
h.Quote.Agency.DC_PLT_Roles.Any(r => r.Name == "Wholesaler")
group new {h} by new {h.PolicyNumber} into g
select new {
XMLData = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.XMLData).FirstOrDefault()
}).ToList();
The key logic is:
select new {
XMLData = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.XMLData).FirstOrDefault()
}).ToList();
Gotta love the Nested Query

SQL "WHERE IN" query conversion to LINQ

I'm trying to find a way to convert this very complex SQL Query into LINQ and I can't seem to tackle all the embedded "WHERE IN" clauses. Would someone be so kind as to lend me a helping hand?
Here is the SQL code (don't worry about the stored procedure, it's a count of a row total)
SELECT
(SELECT pac.Name FROM Account pac WHERE pac.AccountID = AC.ParentAccountID) AS ParentAccountName,
ac.Name, dv.DeviceID, dv.Manufacturer, dv.Model, dv.SerialNr, dv.PrinterIPAddress,
(SELECT TOP 1 au.AuditDate FROM PrinterAudit pa WITH (NOLOCK) INNER JOIN Audit au ON au.AuditID = pa.AuditID
WHERE pa.DeviceID=dv.DeviceID
ORDER BY AuditDate DESC) AS AuditDate,
dbo.Get_TotalPageCountByDeviceId( DATEADD(month, -3, GETDATE()), GETDATE(), dv.DeviceID ) as TotalUsageLast3Months
FROM Account ac WITH (NOLOCK)
INNER JOIN Device dv ON ac.AccountID = dv.AccountID
WHERE dv.AccountID IN
( SELECT au.AccountID FROM Audit au WHERE au.AuditDate >= DATEADD(month, -3, GETDATE()) )
AND (dv.Manufacturer + dv.Model) IN
(SELECT (dv2.Manufacturer + dv2.Model)
FROM Device dv2
WHERE dv2.AccountID = dv.AccountID
AND dv2.Manufacturer = dv.Manufacturer
AND dv2.Model = dv.Model
AND (dv2.ERPEquipID IS NOT NULL OR dv2.ERPData IS NOT NULL ) )
AND dv.ERPEquipID IS NULL AND dv.ERPData IS NULL
AND dv.DeviceID IN
(SELECT pa.DeviceID
FROM PrinterAudit pa WITH (NOLOCK)
INNER JOIN Audit au ON au.AuditID = pa.AuditID
WHERE au.AuditDate >= DATEADD(month, -3, GETDATE()))
ORDER BY ParentAccountName, ac.Name
Final Result:
var result =
(from dv in Device
where Audit.Any(au => au.AuditDate >= DateTime.Now.AddMonths(-3)
&& au.AccountID == dv.AccountID)
where Device.Any(dv2 => dv2.AccountID == dv.AccountID
&& dv2.Manufacturer == dv.Manufacturer
&& dv2.Model == dv.Model
&& (dv2.ERPEquipID != null || dv2.ERPData != null)
&& dv.ERPEquipID == null
&& dv.ERPData == null
&& PrinterAudit.Any(pa => pa.Audit.AuditDate >= DateTime.Now.AddMonths(-3) && pa.DeviceID == dv.DeviceID))
orderby dv.Account.ParentAccountID, dv.Account.Name
select new
{
ParentAccountName = Account.Where(pac => pac.AccountID == dv.Account.ParentAccountID).Select(pac => pac.Name),
Name = dv.Account.Name,
DeviceID = dv.DeviceID,
Manufacturer = dv.Manufacturer,
Model = dv.Model,
SerialNumber = dv.SerialNr,
PrinterIPAddress = dv.PrinterIPAddress,
AuditDate = (from pa in PrinterAudit where pa.DeviceID == dv.DeviceID orderby pa.Audit.AuditDate descending select pa.Audit.AuditDate).Take(1),
TotalUsageLast3Months = (from p in PrinterAudit
where p.DeviceID == dv.DeviceID
group p by p.DeviceID into total
select new
{
Total = Get_TotalPageCountByDeviceId(DateTime.Now.AddMonths(-3), DateTime.Now, dv.DeviceID)
})
});
You convert the SQL IN statement to linq with either Contains or Any
Contains
from dv in db.Device
where
(from au in db.Audit
where au.AuditDate >= DateTime.Now.AddMonths(-3)
select au.AccountID).Contains(dv.AccountID)
Any
from dv in db.Device
where
db.Audit.Any(au => au.AuditDate >= DateTime.Now.AddMonths(-3) &&
au.AccountID == dv.AccountID)