Sql Multi Levels Aggregation - sql

I have this DB diagram:
Considering the relations in the diagram I want to calculate the sum of LikesCount for each RoomType the sum of likes count is to be calculated like that:
RoomTypeLikesCount = Sum(Replays.LikesCount) +
Sum(Comments.LikesCount) +
Sum(Posts.LikesCount)
According to the relation in the diagram as distinct count.
I wonder if there is any simple high performing way.
[Update]
Note: I want to exclude archived or blocked records and just consider rooms with isVisible = true.
My attempt is:
--get comment replays likes, dislikes counts [SUM]
SELECT
C.PostID, C.CommentID,
ISNULL(COUNT(RP.ReplayID), 0) ReplayCount,
ISNULL(C.LikesCount, 0) + ISNULL(SUM(RP.LikesCount), 0) LikesCount,
ISNULL(C.DislikesCount, 0) + ISNULL(SUM(RP.DislikesCount), 0) DislikesCount
INTO
#CommentStats
FROM
CollaborationDB.DiscussionRooms.Comments C
LEFT JOIN
DiscussionRooms.Replays RP ON RP.CommentID = C.CommentID
AND RP.IsBlocked = 0
AND RP.IsArchived = 0
WHERE
c.IsBlocked = 0
AND C.IsArchived = 0
GROUP BY
C.PostID, C.CommentID, C.LikesCount, C.DislikesCount
--get posts views, likes, dislikes counts
SELECT
P.RoomID, P.PostID, P.ViewsCount,
ISNULL(COUNT(CS.CommentID), 0) + ISNULL(SUM(ReplayCount), 0) CommentCount,
ISNULL(P.LikesCount, 0) + ISNULL(SUM(CS.LikesCount), 0) LikesCount,
ISNULL(P.DislikesCount, 0) + ISNULL(SUM(CS.DislikesCount), 0) DislikesCount
INTO
#PostStats
FROM
CollaborationDB.DiscussionRooms.Posts P
LEFT JOIN
#CommentStats CS ON CS.PostID = P.PostID
AND P.IsBlocked = 0
AND P.IsArchived = 0
GROUP BY
P.RoomID, P.PostID, P.ViewsCount, P.LikesCount, P.DislikesCount
--get Room Types Rooms, Posts, views, likes, dislikes counts
SELECT
RT.TypeName,
ISNULL(COUNT(DISTINCT R.RoomID), 0) [RoomsCount],
ISNULL(COUNT(DISTINCT PS.PostID), 0) [PostsCount],
ISNULL(SUM(PS.LikesCount), 0) LikesCount,
ISNULL(SUM(PS.DislikesCount), 0) DislikesCount,
ISNULL(SUM(PS.ViewsCount), 0) ViewsCount
FROM
CollaborationDB.DiscussionRooms.RoomTypes RT
LEFT JOIN
CollaborationDB.DiscussionRooms.Rooms R ON R.RoomTypeID = RT.RoomTypeID
AND R.IsVisible = 1
AND R.IsArchived = 0
LEFT JOIN
#PostStats PS ON PS.RoomID = R.RoomID
WHERE
rt.IsArchived = 0
AND R.IsVisible = 1
AND R.IsArchived = 0
GROUP BY
RT.RoomTypeID, RT.TypeName

Related

Delete Records from table on the basis of inner join

I have two tables in oracle DB called collection and collection_h. I have to delete all the records from collection_h which has the same below fields in the collection table.
I have to delete all the records from collection_h table that comes out as a result of the below query:
select * from collection inner join collection_h on
collection.pos_protocol_id = collection_h.pos_protocol_id and
collection.terminal_pos_number = collection_h.terminal_pos_number and
collection.cb_file_number = collection_h.cb_file_number and
collection.cb_block_number = collection_h.cb_block_number and
collection.is_stan_batch = collection_h.is_stan_batch and
collection.is_transaction_date = collection_h.is_transaction_date and
collection.is_stan_trans = collection_h.is_stan_trans;
Delete where exists
delete
from collection as c
where exists (
select 1
from collection_h as h
where h.pos_protocol_id = c.pos_protocol_id
and h.terminal_pos_number = c.terminal_pos_number
and h.cb_file_number = c.cb_file_number
and h.cb_block_number = c.cb_block_number
and h.is_stan_batch = c.is_stan_batch
and h.is_transaction_date = c.is_transaction_date
and h.is_stan_trans = c.is_stan_trans
);
Simplified test on db<>fiddle here
But if the columns can have NULL's in the matching rows
delete
from collection as c
where exists (
select 1
from collection_h as h
where decode(h.pos_protocol_id, c.pos_protocol_id, 0, 1) = 0
and decode(h.terminal_pos_number, c.terminal_pos_number, 0, 1) = 0
and decode(h.cb_file_number, c.cb_file_number, 0, 1) = 0
and decode(h.cb_block_number, c.cb_block_number, 0, 1) = 0
and decode(h.is_stan_batch, c.is_stan_batch, 0, 1) = 0
and decode(h.is_transaction_date, c.is_transaction_date, 0, 1) = 0
and decode(h.is_stan_trans, c.is_stan_trans, 0, 1) = 0
);
Delete x from collection X inner join collection_h Y on
X.pos_protocol_id = Y.pos_protocol_id and
X.terminal_pos_number = Y.terminal_pos_number and
X.cb_file_number = Y.cb_file_number and
X.cb_block_number = Y.cb_block_number and
X.is_stan_batch = Y.is_stan_batch and
X.is_transaction_date = Y.is_transaction_date and
X.is_stan_trans = Y.is_stan_trans;

Error 1055 SQL - SELECT list is not in GROUP BY

I'm struggling with this SQL consult, the error message is:
1055 - Expression #10 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'ctrl2019.s.cgsc_cuenta' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by.
And here is the code:
SELECT c.cgcu_cuenta AS id,
g.ger_cuenta, g.ger_nombre,
p.cgp_cuenta, p.cgp_nombre,
r.rub_cuenta, r.rub_nombre,
c.cgcu_cuenta, c.cgcu_nombre,
s.cgsc_cuenta, s.cgsc_nombre,
SUM(IFNULL(a.debe, 0)) - SUM(IFNULL(a.haber, 0)) AS debe, 0 AS haber,
'D' AS nat_id,
c.cgcu_cuenta AS cuenta, c.cgcu_nombre AS nombre
FROM ctrl2019.cat_Genero g
INNER JOIN ctrl2019.cat_CgGrupo p USING(ger_id)
INNER JOIN ctrl2019.cat_Rubro r USING(ger_id, cgp_id)
INNER JOIN ctrl2019.cat_CgCuenta c USING(ger_id, cgp_id, rub_id)
INNER JOIN ctrl2019.cat_CgSubcuenta s USING(ger_id, cgp_id, rub_id, cgcu_id)
LEFT JOIN (
SELECT a.ger_id, a.grp_id, a.rub_id, a.cta_id, a.sct_id,
SUM(IFNULL(a.msl_debe, 0)) AS debe, SUM(IFNULL(a.msl_haber, 0)) AS haber
FROM ldf.vin_EntePublicoLDF e
INNER JOIN ldf.blz_Mensual_2019 a USING(gpo_id, ur_id)
WHERE e.ejr_id = 2019
AND a.ger_id = 1
AND e.ent_id = 12
AND a.msc_id IN (0, 1, 2, 3)
GROUP BY a.ger_id, a.grp_id, a.rub_id, a.cta_id, a.sct_id
)a ON s.ger_id = a.ger_id AND s.cgp_id = a.grp_id AND s.rub_id = a.rub_id AND s.cgcu_id = a.cta_id AND s.cgsc_id = a.sct_id
WHERE g.ger_id = 1
GROUP BY g.ger_id, p.cgp_id, r.rub_id, c.cgcu_id;
I have no idea why it gives me this error, i'm new in sql.
you just need to add all the columns in GROUP BY which are present in the SELECT statement.
Seems like simple aggregation here. I cleaned up the code and added some columns to the GROUP BY.
SELECT
id = c.cgcu_cuenta
,g.ger_cuenta
,g.ger_nombre
,p.cgp_cuenta
,p.cgp_nombre
,r.rub_cuenta
,r.rub_nombre
,c.cgcu_cuenta
,c.cgcu_nombre
,s.cgsc_cuenta
,s.cgsc_nombre
,debe = SUM(IFNULL(a.debe, 0)) - SUM(IFNULL(a.haber, 0))
,haber = 0
,nat_id = 'D'
,cuenta = c.cgcu_cuenta
,nombre = c.cgcu_nombre
FROM ctrl2019.cat_Genero g
INNER JOIN ctrl2019.cat_CgGrupo p ON USING(ger_id)
INNER JOIN ctrl2019.cat_Rubro r ON USING(ger_id, cgp_id)
INNER JOIN ctrl2019.cat_CgCuenta c USING(ger_id, cgp_id, rub_id)
INNER JOIN ctrl2019.cat_CgSubcuenta s USING(ger_id, cgp_id, rub_id, cgcu_id)
LEFT JOIN (
SELECT
a2.ger_id
,a2.grp_id
,a2.rub_id
,a2.cta_id
,a2.sct_id
,debe = SUM(IFNULL(a2.msl_debe, 0))
,haber = SUM(IFNULL(a2.msl_haber, 0))
FROM ldf.vin_EntePublicoLDF E
INNER JOIN ldf.blz_Mensual_2019 a2 USING(gpo_id, ur_id)
WHERE e.ejr_id = 2019
AND a2.ger_id = 1
AND e.ent_id = 12
AND a2.msc_id IN (0, 1, 2, 3)
GROUP BY
a2.ger_id
,a2.grp_id
,a2.rub_id
,a2.cta_id
,a2.sct_id
) A
ON s.ger_id = A.ger_id
AND s.cgp_id = A.grp_id
AND s.rub_id = A.rub_id
AND s.cgcu_id = A.cta_id
AND s.cgsc_id = A.sct_id
WHERE g.ger_id = 1
GROUP BY
g.ger_id
,p.cgp_id
,r.rub_id
,C.cgcu_id
,c.cgcu_cuenta
,g.ger_cuenta
,g.ger_nombre
,p.cgp_cuenta
,p.cgp_nombre
,r.rub_cuenta
,r.rub_nombre
,c.cgcu_nombre
,s.cgsc_cuenta
,s.cgsc_nombre

Convert SQL Query to LINQ query/Lambda expression

I am trying to fetch the results from the DB using the Entity Framework using the below SQL query:
SELECT
Header_Id,
Header_Number, Details_Id,
Details_Header_Date,
(SELECT TOP 1 c.[Comment_Description] FROM [Comment] c
WHERE c.[Comment_CarrierId] = i.[Header_CarrierId] AND c.[Comment_ParentEntityId] = i.[Header_Id]
ORDER BY c.Comment_AddedOn DESC) AS 'HeaderComments',
CONCAT(ht.[HeaderTracker_Reason], ' ', ht.[HeaderTracker_Notes]) AS 'RejectedComments',
at.[InternalComments] AS 'InternalComments',
CASE i.[Header_Status]
WHEN 'Pending' THEN ar.[HeaderTracker_ApprovedLvl] END AS 'ApprovedLevel',
CASE i.[Header_Status]
WHEN 'Pending' THEN ar.[HeaderTracker_DueBy] END AS 'ApprovedDueDate'
FROM [Header] i
LEFT OUTER JOIN [Details] ii
ON i.[Header_Id] = ii.[Details_HeaderId]
INNER JOIN [Carrier] t
ON t.[Carrier_Id] = i.[Header_CarrierId]
LEFT OUTER JOIN [HeaderTracker] ht
ON ht.[HeaderTracker_HeaderId] = i.[Header_Id] AND ht.[HeaderTracker_Type] = 'Rejected'
LEFT OUTER JOIN [AdjustmentTracker] at
ON at.[DetailsId] = ii.[Details_Id]
LEFT OUTER JOIN [HeaderTracker] ar
ON ar.[HeaderTracker_HeaderId] = i.[Header_Id]
AND i.[Header_Status] IN ('Paid', 'Pending', 'Approved', 'PaidWithAdj')
AND ar.[HeaderTracker_IsPending] = 1
The result output should be using LINQ query / LAMBDA expression
The following code is what I tried: (not sure how TOP 1 and CASE would come here + if & is also valid here)
var statuses = new string[] { "Paid", "Pending", "Approved", "PaidWithAdj" };
var hdrdet =
(
from hdr in dbContext.Headers
join det in dbContext.Details on hdr.Header_Id equals det.Header_Id into hdrdet
from h in hdrdet.DefaultIfEmpty()
join carr in dbContext.Carriers on hdr.Carrier_Id equals carr.Header_Carrier_Id into carrs
from c in carrs.DefaultIfEmpty()
join hdrtk in dbContext.HeaderTracker on hdr.Header_Id equals hdrtk.HeaderTracker_HeaderId && hdrtk.HeaderTracker_Type equals "Rejected" into hdrtks
from k in hdrtks.DefaultIfEmpty()
join adjt in dbContext.AdjustmentTracker on adjt.DetailsId equals det.Details_Id into adjts
from a in adjts.DefaultIfEmpty()
join pnd in dbContext.HeaderTracker on pnd.HeaderTracker_HeaderId equals hdr.Header_Id && hdr.Header_Status contains(statuses) && pnd.[HeaderTracker_IsPending] equals 1 into pnds
from p in pnds.DefaultIfEmpty()
select new
{
hdrid = Header_Id,
hdrnumber = Header_Number, Details_Id,
det_date = Details_Header_Date,
reason = HeaderTracker_Reason + ' ' + HeaderTracker_Notes,
intcomments = InternalComments
}
)

SQL Counting Records with Count and Having

I'm having problems with what I thought was a simple query to count records:
SELECT req_ownerid, count(req_status_lender) AS total6
FROM bor_requests
WHERE (req_status_lender = 0 AND req_status_borrower = 0) OR
(req_status_lender = 1 AND req_status_borrower = 1)
GROUP BY req_ownerid
HAVING req_ownerid = 70
I thought this would count all the records where (req_status_lender = 0 AND req_status_borrower = 0) and (req_status_lender = 1 AND req_status_borrower = 1) and then give me the total but it only gives me the total for either (req_status_lender = 0 AND req_status_borrower = 0) or (req_status_lender = 1 AND req_status_borrower = 1).
Any ideas what I'm doing wrong?
You should use the HAVING clause only to limit on something that's been aggregated in your query above - e.g. if you want to select all those rows where a SUM(....) or COUNT(...) is larger than say 5, then you'd use HAVING SUM(...) > 5
What you're doing here is a standard WHERE clause - add it there!
SELECT req_ownerid, count(req_status_lender) AS total6
FROM bor_requests
WHERE req_ownerid = 70
AND ((req_status_lender = 0 AND req_status_borrower = 0) OR
(req_status_lender = 1 AND req_status_borrower = 1))
GROUP BY req_ownerid

sql: where subquery not null

I have the following sql query and I want to filter the results where the alias imagefile is null, but I can't get it to work. it's kinda basic sql... sorry for that!
SELECT Categorie.CategorieID, Categorie.Highlight, CategorieTaal.CategorieNaam,
(SELECT TOP (1) ImageFile
FROM Artikel WHERE (CategorieID = Categorie.CategorieID)
AND (Onzichtbaar = 0)
AND (NietBestelbaar = 0)
AND (Voorraad = - 1000 OR Voorraad > LevertijdDrempel)
ORDER BY Volgnummer, ArtikelID DESC) AS 'imagefile'
FROM Categorie INNER JOIN
CategorieTaal ON
Categorie.CategorieID = CategorieTaal.CategorieID
WHERE (Categorie.CategorieGroepID = #catgroepid)
AND (Categorie.Onzichtbaar = 0)
AND (CategorieTaal.TaalCode = #tc)
ORDER BY Categorie.Volgnummer, CategorieTaal.CategorieNaam
You might want to try this:
SELECT Categorie.CategorieID, Categorie.Highlight, CategorieTaal.CategorieNaam,
FROM Categorie
INNER JOIN
CategorieTaal ON
Categorie.CategorieID = CategorieTaal.CategorieID
WHERE (Categorie.CategorieGroepID = #catgroepid)
AND (Categorie.Onzichtbaar = 0)
AND (CategorieTaal.TaalCode = #tc)
AND NOT EXISTS (SELECT 1 ImageFile
FROM Artikel WHERE (CategorieID = Categorie.CategorieID)
AND (Onzichtbaar = 0)
AND (NietBestelbaar = 0)
AND (Voorraad = - 1000 OR Voorraad > LevertijdDrempel))
ORDER BY Categorie.Volgnummer, CategorieTaal.CategorieNaam
You can optimize this by using an inner join again, in lieu of trying to use a subquery twice:
SELECT
c.CategorieID,
c.Highlight,
ct.CategorieNaam,
a.ImageFile
FROM
Categorie c
INNER JOIN CategorieTaal ct ON
c.CategorieID = ct.CategorieID
INNER JOIN
(select
CategorieID,
ImageFile,
row_number() over (partition by CategorieID) as rownum
from
Artikel
where
Onzichtbaar = 0
and NietBestelbaar = 0
and (Voorraad = -1000 OR Voorraad > LevertijdDrempel)) a ON
c.CategorieID = a.CategorieID
and a.rownum = 1
WHERE
c.CategorieGroepID = #catgroepid
AND c.Onzichtbaar = 0
AND ct.TaalCode = #tc
ORDER BY c.Volgnummer, ct.CategorieNaam
Since you're using SQL Server (or at least I think you are, with your top and whatnot), you can take advantage of row_number. This will bring back just the ImageFile you need, without having to do two correlated subqueries (usually performance killers).
Also, here you only have to maintain that subquery in one place, not in two different parts of your query.
found it!!
SELECT Categorie.CategorieID, Categorie.Highlight, CategorieTaal.CategorieNaam,
(SELECT TOP (1) ImageFile
FROM Artikel
WHERE (CategorieID = Categorie.CategorieID)
AND (Onzichtbaar = 0)
AND (NietBestelbaar = 0)
AND (Voorraad = - 1000
OR Voorraad > LevertijdDrempel)
ORDER BY Volgnummer, ArtikelID DESC) AS 'imagefile'
FROM Categorie
INNER JOIN CategorieTaal ON Categorie.CategorieID = CategorieTaal.CategorieID
WHERE (Categorie.CategorieGroepID = #catgroepid)
AND (Categorie.Onzichtbaar = 0)
AND (CategorieTaal.TaalCode = #tc)
AND ((
SELECT TOP (1) ImageFile
FROM Artikel AS Artikel_1
WHERE (CategorieID = Categorie.CategorieID)
AND (Onzichtbaar = 0)
AND (NietBestelbaar = 0)
AND (Voorraad = - 1000
OR Voorraad > LevertijdDrempel)
) IS NOT NULL)
ORDER BY Categorie.Volgnummer, CategorieTaal.CategorieNaam