Linq to SQL: how to aggregate without a group by? - linq-to-sql

I am searching for the Linq-to-SQL equivalent to this query:
SELECT
[cnt]=COUNT(*),
[colB]=SUM(colB),
[colC]=SUM(colC),
[colD]=SUM(colD)
FROM myTable
This is an aggregate without a group by. I can't seem to find any way to do this, short of issuing four separate queries (one Count and three Sum). Any ideas?

This is what I found seems like you still have to do a group by...can just use constant:
var orderTotals =
from ord in dc.Orders
group ord by 1 into og
select new
{
prop1 = og.Sum(item=> item.Col1),
prop2 = og.Sum(item => item.Col2),
prop3 = og.Count(item => item.Col3)
};
This produces the following SQL, which is not optimal, but works:
SELECT SUM([Col1]) as [prop1], SUM([Col2]) as [prop2], COUNT(*) AS [prop3]
FROM (
SELECT 1 AS [value], [t0].[Col1], [t0].[Col2], [t0].[Col3]
FROM [table] AS [t0]
) AS [t1]
GROUP BY [t1].[value]

You can do the same query using Lambda expression as follows:
var orderTotals = db.Orders
.GroupBy( i => 1)
.Select( g => new
{
cnt = g.Count(),
ScolB = g.Sum(item => item.ColB),
ScolC = g.Sum(item => item.ColC)
});

Related

SQL - How can I combine Select Statements?

Is there any way to apply Logical Operator -> OR between 2 Select statements?
I am open to another other solutions which satisfies above OR Condition.
If there is no data in 1st Select then goto next Select
Example
SELECT column1, column2
FROM table-name1 JOIN table-name2
ON column-name1 = column-name2
WHERE //all condition
OR
SELECT column3, column4
FROM table-name3 JOIN table-name4
ON column-name3 = column-name4
WHERE //all condition
Condition 1/ Query 1
async getData() {
try {
const data = await this._conn.query(`
select first_name.value_name,quiz_table.answer, windows,player,first_name.value_id,country_place,current_name, pet_name, marker, relations
from schema_name.plugin,schema_name.quiz_table,schema_name.first_name, schema_name.value_version, schema_name.relationss
where plugin.answer= quiz_table.answer
and quiz_table.windows=first_name.value_id
and marker is not null
and schema_name.value_version.value_id= schema_name.first_name.value_id
and schema_name.value_version.caste= schema_name.first_name.caste
and schema_name.value_version.value_name= schema_name.first_name.value_name
and schema_name.value_version.version_number= schema_name.first_name.version_number
and schema_name.relationss.value_id= schema_name.first_name.value_id
and schema_name.relationss.caste= schema_name.first_name.caste
and schema_name.relationss.value_name= schema_name.first_name.value_name
and schema_name.relationss.version_number= schema_name.first_name.version_number
and schema_name.quiz_table.windows= schema_name.first_name.value_id
and in_process='N'
}
OR
Condition 2/ Query 2 - Display data
select schema_name.relationss."relations", schema_name.quiz_table."answer", schema_name.quiz_table."windows", schema_name.quiz_table."in_process", schema_name.quiz_table."object_name", schema_name.quiz_table."processed_date", schema_name.quiz_table."player", schema_name.quiz_table."country_place", schema_name.tools."mesh_scope_note", schema_name.plugin."current_name", schema_name.plugin."pet_name"
from schema_name.quiz_table, schema_name.tools, schema_name.plugin, schema_name.relationss, schema_name.value_version
where (in_process = 'N'
and schema_name.quiz_table."windows" = schema_name.tools."value_id"
and schema_name.quiz_table."player" = schema_name.tools."language"
and schema_name.quiz_table."answer" = schema_name.plugin."answer"
and schema_name.relationss."language" = schema_name.quiz_table."player"
and schema_name.relationss."language" = schema_name.tools."language"
and schema_name.relationss."caste" = schema_name.tools."caste"
and schema_name.relationss."value_name" = schema_name.tools."value_name"
and schema_name.relationss."version_number" = schema_name.tools."version_number"
and schema_name.relationss."value_id" = schema_name.tools."value_id"
and schema_name.value_version."value_id" = schema_name.tools."value_id"
and schema_name.value_version."version_number" = schema_name.tools."version_number"
and schema_name.value_version."caste" = schema_name.tools."caste"
)
NOTE- In WHERE clause both Select has different conditions
A simple method is union all and exists -- well, assuming the two selects return the same column:
with cte as (
select . . .
)
select *
from cte
union all
select *
from t2
where not exists (select 1 from cte);

Zf2 table gateway join query to fetch only the latest row(by id) from second table

Hi, I need a zf2 join query that fetches only the latest row(by id DESC) from the second table. I have written an sql query and it works.
SELECT st1.customer_id,
st1.id
FROM status st1
inner JOIN
(
SELECT max(id) MaxId, customer_id
FROM status
GROUP BY customer_id
) st2
ON st1.customer_id = st2.customer_id
AND st1.id = st2.MaxId
But I need this query at zend framework 2 table gateway format. Please help.
use Zend\Db\Sql\Select;
use Zend\Db\Sql\Expression;
$sql = new Select ();
$sql->columns(["customer_id", new Expression ("max(id) AS MaxId")])
->from ('status')
->group('customer_id');
$outer = new Select ();
$outer->columns (['customer_id', 'id'])
->from (['st1' => 'status'])
->join (['st2' => $sql],
'st1.customer_id = st2.customer_id AND st1.id = st2.MaxId', []);

Matching all values in IN clause

Is there a way to ensure all values in an IN clause are matched?
Example:
I can use IN as: IN (5,6,7,8).
I need it to work like an AND across multiple rows.
UPDATE:
I need this to list companies from db that fit specified parameters. Companies and taxonomy are MANY TO MANY relation. I'm using Yii framework. And this is the code of my controller:
public function actionFilters($list)
{
$companies = new CActiveDataProvider('Company', array(
'criteria' => array(
'condition'=> 'type=0',
'together' => true,
'order'=> 'rating DESC',
'with'=>array(
'taxonomy'=>array(
'condition'=>'term_id IN ('.$list.')',
)
),
),
));
$this->render('index', array(
'companies'=>$companies,
));
}
You can do something like this:
select ItemID
from ItemCategory
where CategoryID in (5,6,7,8) <-- de-dupe these before building IN clause
group by ItemID
having count(distinct CategoryID) = 4 <--this is the count of unique items in IN clause above
If you provide your schema and some sample data, I can provide a more relevant answer.
SQL Fiddle Example
If you want to find the items that have all of a specific set of CategoryIDs and no others, this is one way you can approach it:
select a.ItemID
from (
select ItemID, count(distinct CategoryID) as CategoryCount
from [dbo].[ItemCategory]
where CategoryID in (5,6,7,8)
group by ItemID
having count(distinct CategoryID) = 4
) a
inner join (
select ItemID, count(distinct CategoryID) as CategoryCount
from [dbo].[ItemCategory]
group by ItemID
) b on a.ItemID = b.ItemID and a.CategoryCount = b.CategoryCount
SQL Fiddle Example
If you prefer, you could do it with a subquery:
select ItemID
from ItemCategory
where ItemID in (
select ItemID
from ItemCategory
where CategoryID in (5,6,7,8)
group by ItemID
having count(distinct CategoryID) = 4
)
group by ItemID
having count(distinct CategoryID) = 4
SQL Fiddle Example
SELECT ItemID
FROM ItemCategory
WHERE (
(CategoryID = 5) OR
(CategoryID = 6) OR
(CategoryID = 7) OR
(CategoryID = 8)
)
GROUP BY ItemID
HAVING COUNT(DISTINCT CategoryID) = 4

L2E: GroupBy always gets translated into Distincts, never Group By

How can I get the Linq-to-Entities provider to truly perform a GROUP BY? No matter what I do, it always generates SQL that is far slower than an actual GROUP BY. For example:
var foo = (from x in Context.AccountQuantities
where x.AccountID == 27777
group x by x.StartDate
into groups
select new
{
groups.FirstOrDefault().StartDate,
Quantity = groups.Max(y => y.Quantity)
}).ToList();
translates to:
SELECT
1 AS [C1],
[Project4].[C1] AS [C2],
[Project4].[C2] AS [C3]
FROM ( SELECT
[Project3].[C1] AS [C1],
(SELECT
MAX([Extent3].[Quantity]) AS [A1]
FROM [dbo].[AccountQuantities] AS [Extent3]
WHERE (27777 = [Extent3].[AccountID]) AND ([Project3].[StartDate] = [Extent3].[StartDate])) AS [C2]
FROM ( SELECT
[Distinct1].[StartDate] AS [StartDate],
(SELECT TOP (1)
[Extent2].[StartDate] AS [StartDate]
FROM [dbo].[AccountQuantities] AS [Extent2]
WHERE (27777 = [Extent2].[AccountID]) AND ([Distinct1].[StartDate] = [Extent2].[StartDate])) AS [C1]
FROM ( SELECT DISTINCT
[Extent1].[StartDate] AS [StartDate]
FROM [dbo].[AccountQuantities] AS [Extent1]
WHERE 27777 = [Extent1].[AccountID]
) AS [Distinct1]
) AS [Project3]
) AS [Project4]
How can I get it to execute this instead?
SELECT
AccountQuantities.StartDate,
MAX(AccountQuantities.Quantity)
FROM AccountQuantities
WHERE AccountID=27777
GROUP BY StartDate
Again, note the lack of ANY GROUP BY in what's executed. I'm fine with EF optimizing things non-ideally but this is orders of magnitude slower, I cannot find any way to convince it to really do a GROUP BY, and is a major problem for us!
Use groups.Key instead of groups.FirstOrDefault().StartDate
var foo = (from x in Context.AccountQuantities
where x.AccountID == 27777
group x by x.StartDate
into groups
select new
{
groups.Key,
Quantity = groups.Max(y => y.Quantity)
}).ToList();

Linq outer join with grouping in subquery

I need to convert the following correlated subquery in Linq to Sql. I am able to achieve the left outer join part. However, grouping in a subquery is where i am getting incorrect results.
SELECT
ae.Id,ae.Title
,(select COUNT(*) from [dbo].[AssociationEventRSVP] where RSVPStatus='Y'
group by AssociationEventId, RSVPStatus having RSVPStatus='Y'
and AssociationEventId=ar.AssociationEventId) as CountYes
,(select COUNT(*) from [dbo].[AssociationEventRSVP]
group by AssociationEventId, RSVPStatus having RSVPStatus='N'
and AssociationEventId=ar.AssociationEventId) as CountNo
FROM [dbo].[AssociationEvents] as ae
left outer join AssociationEventRSVP as ar
on ae.Id=ar.AssociationEventId
Thanks in advance for your help.
Tushar M.
I'd first refactor your query to this:
SELECT
ae.Id,
ae.Title,
(select COUNT(*) FROM [dbo].[AssociationEventRSVP] WHERE RSVPStatus='Y' AND AssociationEventId=ae.Id) AS CountYes,
(select COUNT(*) FROM [dbo].[AssociationEventRSVP] WHERE RSVPStatus='N' AND AssociationEventId=ae.Id) AS CountNo
FROM [dbo].[AssociationEvents] as ae
And here's a simple (not necessarily efficient) LINQ to SQL conversion:
var results = from ae in context.AssociationEvents
select new
{
ae.Id,
ae.Title,
CountYes = context.AssociationEventRSVP.Where(aer => aer.RSVPStatus == "Y" && aer.AssociationEventId == ae.Id).Count(),
CountNo = context.AssociationEventRSVP.Where(aer => aer.RSVPStatus == "N" && aer.AssociationEventId == ae.Id).Count()
};