Nested Select Count Query with Criteria - nhibernate

say that we have 2 entity EntityA and EntityB , with the related tables, TableA and TableB.
i have to implement this query:
select a.Id , (select count(b.Id) from TableB b where b.FKa = a.Id and b.AnotherField > 0) as TheCount
from TableA a
i'm very close to that since i wrote this code:
var subCrit = DetachedCriteria.For<EntityB>
.Add<EntityB>(e => e.AnotherField > 0)
.SetProjection(LambdaProjection.Count<EntityB>(e => e.Id).As("TheCount"));
var crit = Session.CreateCriteria<EntityA>
.SetProjection(LambdaProjection.GroupProperty<EntityA>(e => e.Id).As("Id),
Projections.SubQuery(subCrit));
if i execute this criteria i obtain the following SQL:
select a.Id as Id , (select count(b.Id) from TableB b where b.AnotherField > 0) as TheCount from TableA a
as u can see , it's very close to what i'm trying to achieve...the problem (and it's definetely a big problem :D)
is that theres no link between the subquery and the entities of TableA ( where b.FKa = a.Id ).
I cant find a way to correlate the subquery to the external query via criteria.
Any suggestions ?
Ta a lot
Alessandro
EDIT:
changing the point of view i also could do something like that:
var crit = Session.CreateCriteria<EntityA>()
.CreateAlias<EntityB>(a => a.B, () => b);
.SetProjection(LambdaProjection.Count<A>(a => b.Id).As("TheCount"),
.SetProjection(LambdaProjection.GroupProperty<EntityA>(a => a.Id));
and this is generating the following sql:
select count(b.Id) as TheCount, a.Id as IDa
from TableA a left outer join TableB b
on a.Id = b.FKa
group by a.Id
but here you can see that the additional where clause b.AnotherField > 0 is missing , and i dont know how to insert it just for the count.
Hope it's clear , thanks again

Here is the solution:
var condition = Expression.Gt("b.AnotherField",0);
var conditionalProjection = Projections.Conditional(condition, Projections.Constant(1), Projections.Constant(0));
crit = Session.CreateCriteria<EntityA>()
.CreateAlias<EntityB>(a => a.B, () => b);
.SetProjection(Projections.Count(conditionalProjection).As("TheCount"),
(LambdaProjection.GroupProperty<EntityA>(a => a.Id));
and this is the sql generated:
select count(case b.AnotherField > 0 then 1 else 0 end) as TheCount , a.Id
from TableA a inner join TableB b
hope it can be useful
cheers
Alessandro
enter code here

My suggestion is to change the SQL Statement
SELECT a.is, count(a.id)
FROM TableA a
JOIN TableB b ON a.id = b.fka AND b.af > 0
GROUP by a.ID
And create for it easy criteria.

Related

How to SELECT a.* FROM a WHERE EXCEPT SELECT b.* FROM b WHERE a.id != b.id

I am having quite a struggle with the presented postgres request.
I have a table objects with a few columns, including an id column.
I have a table object_couples that references couples of objects with id. This table contains in consequence 2 columns of ids.
I have an external variable, like int external_variable = 42.
I am trying to select every entry of the objects table where the id of the selected object and the id of the external_variable does not exist as a couple in the object_couples table.
My request looks like the following :
SELECT id, c1, c2
FROM objects
WHERE condition1 AND condition2
EXCEPT SELECT left_id, right_id
FROM object_couples
WHERE objects.id != object_couples.left_id
AND external_variable != object_couples.right_id;
What can I do?
EDIT 1 :
The following request is not rejected but causes in pycharm a code 137(SIGKILL) :
SELECT id, c1, c2
FROM objects AS S
INNER JOIN object_couples
ON object_couples.left_id != S.id
AND object_couples.right_id != external_variable
WHERE S.c1 > 1234 AND S.c2 < 5678```
I am thinking not exists:
select o.*
from objects o
where not exists (select 1
from object_couples oc
where (oc.id = oc.left and 42 = oc.right) or
(oc.id = oc.right and 42 = oc.left)
);
For performance, you might find that this works better:
select o.*
from objects o
where not exists (select 1
from object_couples oc
where oc.id = oc.left and 42 = oc.right
) and
not exists (select 1
from object_couples oc
where oc.id = oc.right and 42 = oc.left
);
In particular if you have indexes on object_couples(left, right) and object_couples(right, left) then this might even be fast.

How to find a value if we have 2 same columns in 2 different tables?

As you can see on the photo. I have 2 tables(A and B). KlantId is common in 2 tables. What I want to achieve is, if I provide the Email then I can get the reservatieNummer.
select b.reservatieID
from tablea as a
inner join tableb as b on a.KlantId = b.KlantId
where a.email="whatever"
and you specify the email in the where condition
To use linq:
var ReservatieID = tableA.Join(tableB, ta =>ta.KlantId, tb =>tb.KlantId, (ta,tb) =>new{tableA = ta, tableB = tb})
.Where(a=> a.email == "whatever#domain.com").Select(a=> new{a.reservatieID});

Selecting ONLY Duplicates from a joined tables query

I have the following query that I'm trying to join two tables matching their ID so I can get the duplicated values in "c.code". I've tried a lot of queries but nothing works. I have a 500k rows in my database and with this query I only get 5k back, which is not right. Im positive it's at least 200K. I also tried to use Excel but it's too much for it to handle.
Any ideas?
Thanks in advance, everyone.
SELECT c.code, c.name as SCT_Name, t.name as SYNONYM_Name, count(c.code)
FROM database.Terms as t
join database.dbo.Concepts as c on c.ConceptId = t.ConceptId
where t.TermTypeCode = 'SYNONYM' and t.ConceptTypeCode = 'NAME_Code' and c.retired = '0'
Group by c.code, c.name, t.name
HAVING COUNT(c.code) > = 1
Order by c.code
with data as (
select c.code, c.name as SCT_Name, t.name as SYNONYM_Name
from database.Terms as t inner join database.dbo.Concepts as c
on c.ConceptId = t.ConceptId
where
t.TermTypeCode = 'SYNONYM'
and t.ConceptTypeCode = 'NAME_Code'
and c.retired = '0'
)
select *
--, (select count(*) from data as d2 where d2.code = data.code) as code_count
--, count(*) over (partition by code) as code_count
from data
where code in (select code from data group by code having count(*) > 1)
order by code
If you want just duplicates of c.code, your Group By is wrong (and so is your Having clause). Try this:
SELECT c.code
FROM database.Terms as t
join database.dbo.Concepts as c on c.ConceptId = t.ConceptId
where t.TermTypeCode = 'SYNONYM' and t.ConceptTypeCode = 'NAME_Code' and c.retired = '0'
Group by c.code
HAVING COUNT(c.code) > 1
This will return all rows where you have more than one c.code value.
You need to use INTERSECT instead of JOIN. Basically you perform the select on the first table then intersect with the second table. The result is the duplicate rows.
Only select the id column, though, otherwise the intersect won't work as expected.

Converting SQL to LINQ (left join on two fields)

I need help to convert this expression to LINQ.
In this example:
TableA[IDTABLE_A, NAME]
TableA[IDTABLE_B, IDTABLE_A, REL]
SELECT *
FROM TableA a
LEFT JOIN TableB b
ON a.IDTABLE_A = b.IDTABLE_A
AND b.IDTABLE_B = 3
Thanks in advance.
Try this:-
var query = from a in data1
join b in data2.Where(x => x.BID == 3)
on a.AID equals b.AID into ab
from c in ab.DefaultIfEmpty()
select new
{
AID = a.AID,
AName = a.AName,
BName = c == null ? "No Records" : c.BName
};
Complete Working Fiddle Here.

Remove repeated values from the table

I have a PL/SQL select query like,
select
a.sgm,
b.numbr
from tbl1 a, tbl2 b
where b.itemId = a.itemId
and b.orgId = a.orgId
and a.srvCode = 'F'
and a.nbrCode <> 1
and rownum <= 7
Right now it retrieves like ,
sgm-|-numbr
-----------
abc-|-123
abc-|-678
abc-|-78
abc-|-099
bcd-|-153
bcd-|-123
bcd-|-123
I need to retrieve like ,
sgm-|-numbr
-----------
abc-|-123
bcd-|-153
ie, I need to remove the repeated ones in the first column. ie sgm shouldn't repeat.
Since you are using Oracle, then try this simplified version using a CTE:
WITH CTE as (
SELECT sgm, numbr,
rownum rn
FROM YourTable
)
SELECT CTE.sgm, CTE.numbr
FROM CTE
JOIN (
SELECT sgm, MIN(rownum) minrn
FROM CTE
GROUP BY sgm) t ON CTE.sgm = t.sgm AND CTE.rn = t.minrn
http://sqlfiddle.com/#!4/8d6fb/10
You can replace your query in the CTE above.
Good luck.
SELECT a.sgm, MAX(b.numbr)
FROM tbl1 a INNER JOIN tbl2 b
ON a.itemID = b.itemId
AND a.orgId = b.orgId
WHERE a.srvCode= 'F'
AND a.nbrCode <> 1
AND rownum <= 7
GROUP BY a.sgm
Apply a group function of your choice like MAX() on b.numbr, and apply the grouping on a.sgm, this should do what you need.
Advice : do your joins explicitly, see the difference between your query and mine.
select a.sgm,MAX(b.numbr)
from tbl1 a, tbl2 b
where b.itemId = a.itemId
AND b.orgId= a.orgId
and a.srvCode= 'F'
and a.nbrCode <> 1
and rownum<=7
group by sgm
The value of sgm wont repeat, but maximum value of number will be selected, similarly you can also select the minimum value using the Min function
Use group by function
select
a.sgm,
b.numbr
from tbl1 a, tbl2 b
where b.itemId = a.itemId
and b.orgId = a.orgId
and a.srvCode = 'F'
and a.nbrCode <> 1
and rownum <= 7
group by a.sgm
Select a from tbl a , tbl b WHERE a.userid > b..userid and
a.sgm = b.sgm;
Check this fiddle http://sqlfiddle.com/#!2/40b8f/2