SQLite unsure about ALL syntax [duplicate] - sqlite

This question already has answers here:
SQLite syntax for "ALL"
(3 answers)
Closed last month.
I'm trying to find out which customer spent the most on orders, in addition to how much they have spent in total.
This is my current code. However, im getting a syntax error near ALL
SELECT c.id, sum(i.Quantity * p.UnitPrice) AS TotalSpend
FROM Customers c, Orders o, OrderItems i, Products p
WHERE c.id = o.CustomerID
AND o.id = i.OrderID
AND i.ProductID = p.id
AND sum(i.Quantity * p.UnitPrice) > ALL(
SELECT sum(i.Quantity * p.UnitPrice)
FROM OrderItems i, Products p
WHERE i.ProductID = p.id)
Not too sure where i have committed the syntax error

Apparently the keyword ALL is not supported by SQLite.

Related

EF Core - Count from a specific column

I almost have my EF Core query working... This is the SQL getting produced (notice the Count(*):
SELECT [u].[Key], [u].[Url], [u].[CreatedBy], [u].[CreatedOn], COUNT(*) AS [Clicks]
FROM [URLs] AS [u]
LEFT JOIN [OwnerUrls] AS [o] ON [u].[Key] = [o].[ShortUrlKey]
LEFT JOIN [Clicks] AS [c] ON [u].[Key] = [c].[ShortUrlKey]
GROUP BY [u].[Key], [u].[Url], [u].[CreatedBy], [u].[CreatedOn]
What I need is (have Count look at a specific column/table)
SELECT [u].[Key], [u].[Url], [u].[CreatedBy], [u].[CreatedOn], COUNT(c.ID) AS [Clicks]
FROM [URLs] AS [u]
LEFT JOIN [OwnerUrls] AS [o] ON [u].[Key] = [o].[ShortUrlKey]
LEFT JOIN [Clicks] AS [c] ON [u].[Key] = [c].[ShortUrlKey]
GROUP BY [u].[Key], [u].[Url], [u].[CreatedBy], [u].[CreatedOn]
Here is the EF Query that I'm using...
query = (from u in db.URLs
join ou in db.OwnerUrls on u.Key equals ou.ShortUrlKey into urlOwners
from subSet in urlOwners.DefaultIfEmpty()
join c in db.Clicks on u.Key equals c.ShortUrlKey into urlClicks
from subClicks in urlClicks.DefaultIfEmpty()
group subClicks by new { u.Key, u.Url, u.CreatedBy, u.CreatedOn } into g
select new ShortURL()
{
Key = g.Key.Key,
Url = g.Key.Url,
CreatedBy = g.Key.CreatedBy,
CreatedOn = g.Key.CreatedOn,
Clicks = g.Count()
});
I've tried changing the g.Count() to g.Select(x=>x.Id).Count() and that just causes EF Core to barf and complain about client side evaluation vs server side evaluation etc..
I should mention that the reason I'm joining the first model (OwnerUrls) is to support a where clause that I didn't include here...
Thanks!
I'm not a EF developer, but have worked with SQL Server for a while now. In SQL Server i would use COUNT(DISTINCT c.ID) to eliminate any duplicates you might get from JOINS.
If duplicates are impossible due to the model the COUNT(*) shoud be sufficient.
Maybe this might help:
https://entityframeworkcore.com/knowledge-base/51892585/linq-select-distinct-count-performed-in-memory

How to do arithemtic operations with an alias in sqlite

I want to calculate with an alias in sqlite (Example is modified from http://www.sqlitetutorial.net):
if i do it like this, i get the error message "no such column: tracks_count"
SELECT albumid,
title,
(
SELECT count(trackid)
FROM tracks
WHERE tracks.AlbumId = albums.AlbumId
)
tracks_count, tracks_count * album_nr
FROM albums
ORDER BY tracks_count DESC;
if i do it like this, i get zero for the mulitplication
SELECT albumid,
title,
(
SELECT count(trackid)
FROM tracks
WHERE tracks.AlbumId = albums.AlbumId
)
tracks_count, "tracks_count" * album_nr
FROM albums
ORDER BY tracks_count DESC;
Table data for the example:
table albums
table tracks
You don't even need a subquery here:
SELECT
a.albumid,
a.title,
COUNT(t.albumid) AS tracks_count,
COUNT(t.albumid) * a.album_nr AS other_count
FROM albums a
LEFT JOIN tracks t
ON a.albumid = t.albumid
GROUP BY
a.albumid,
a.title;
If you wanted to make your current approach work, then the problem you are having is that you are referring to the tracks_count alias in the same select in which it was defined. This isn't allowed, because the alias may not have even been computed yet. But, I would recommend using the answer I gave above.

Google BigQuery - Updating nested Revenue fields

I tried to apply the solution in Google BigQuery - Updating a nested repeated field to the field hits.transaction.transactionRevenue, but I receive error message:
Scalar subquery produced more than one element
I have tried to run the following query:
UPDATE `project_id.dataset_id.table`
SET hits = ARRAY(
SELECT AS STRUCT * REPLACE (
(SELECT AS STRUCT transaction.* REPLACE (1 AS transactionRevenue)) AS transaction
)
FROM UNNEST(hits) as transactionRevenue
)
WHERE (select h.transaction.transactionId from unnest(hits) as h) LIKE 'ABC123XYZ'
Are there any obvious mistakes on my part? Would be great if anyone could share some tips or experiences that could help me with this.
What I basically want to do is to set the revenue of a specific transaction to 1.
Many thanks in advance,
David
This is the problem:
WHERE (select h.transaction.transactionId from unnest(hits) as h) LIKE 'ABC123XYZ'
If there is more than one hit in the array, this will cause the error that you are seeing. You probably want this instead:
WHERE EXISTS (select 1 from unnest(hits) as h WHERE h.transaction.transactionId LIKE 'ABC123XYZ')
But note that your UPDATE will now replace all elements of the array for any row where this condition is true. What you may want is to move the condition inside the ARRAY function call instead:
UPDATE `project_id.dataset_id.table`
SET hits = ARRAY(
SELECT AS STRUCT * REPLACE (
(SELECT AS STRUCT transaction.* REPLACE (1 AS transactionRevenue)) AS transaction
)
FROM UNNEST(hits) as h
WHERE h.transaction.transactionId LIKE 'ABC123XYZ'
)
WHERE true
Now the replacement will only apply to hits with a transaction ID matching the pattern.

How to use one param in multiple places in birt report [duplicate]

This question already has an answer here:
Birt Report Multiple Parameters for the same field
(1 answer)
Closed 6 years ago.
I want to pass one param in birt report and use it in multiple palces , for example :
SELECT * FROM tab1 WHERE startDAte = trunc(sysdate)
UNION
SELECT *FROM tab1 WHERE startDate= trunc(sysdate-1)
So i want to make sysdate like a variable :
SELECT * FROM tab1 WHERE startDAte = trunc(?)
UNION
SELECT *FROM tab1 WHERE startDate= trunc(?-1)
How can i do that ? Thanks
This has already been answered in Reusing an anonymous parameter in a prepared statement
If your database is Oracle, you can also use the following syntax:
WITH params AS
( select ? as p_date,
? as p_whatever,
...
from dual
)
SELECT tab1.* FROM tab1, params WHERE tab1.startDate = trunc (params.p_date)
UNION
SELECT tab1.* FROM tab1, params WHERE startDate= trunc (parms.p_date - 1)
Note that this does not have a negative performance impact, because the DB is clever enough to detect that the params inline-view contains exactly one row.

SELECT MAX() contained within a DATEDIFF()

I am writing a report for the desktop support team in the company where I work. The report needs to produce a set of new starters within a specified time frame passed in from an ASP.NET application. Currently there is a one to many relationship between our Worker table and Contract table. We hire a lot of contractors and they sometimes come back after a number of months but are still treated like new starters as new machines need to be configured along with desk space.
A new contract is added for every pay review, job title change and new starter. We need to filter out all but the new starter. The newest contract that is added for job changes and pay reviews is always one day after the end date of the previous contract naturally. As I am only still a fresher in the grand scheme of things I am struggling with a set of functions I am trying to use to achieve my goal.
WHERE
(dbo.[Contract].StartDate BETWEEN #StartDateF AND #EndDateF) AND DATEDIFF(day, SELECT MAX(StartDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID, SELECT MAX(EndDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID)> 1
I basically want to find out in the instance an employee has more than one contract, regardless of leaving and coming back or pay review, if the current active contract is one day different to the previous contract. This should by my thinking give me all new starters only.
Trouble is I am still trying to get my head around when to use aggregate functions not in a select and when to apply the HAVING clause.
Any help would be appreciated to help me understand why my lack of understanding is causing this query/logic to fail.
Thanks
EDIT
Ok I am still bashing away at this solution and this is syntactically incorrect. In an attempt to remove some of the ambiguity here is the query, with an update;
Declare #StartDateF varchar(10)
Set #StartDateF = '2012-08-03'
Declare #EndDateF varchar(10)
Set #EndDateF = '2012-09-04'
SELECT w1.Worker_ID, w1.Title, w1.FirstName, w1.Surname,w1.Gender, w1.DateofBirth,
dbo.[Contract].StartDate, (select w2.surname + ',' + w2.firstname from worker w2 WITH (NOLOCK) where w2.worker_ID = w1.manager)as Manager, dbo.Grade.GradeDescription AS JobTitle, dbo.Grade.Discipline,
CASE WHEN dbo.[Contract].ContractType_ID = 1 OR dbo.[Contract].ContractType_ID = 2 OR dbo.[Contract].ContractType_ID = 5 OR dbo.[Contract].ContractType_ID = 6
THEN 'Staff' ELSE 'Contractor' END AS ContractType
FROM dbo.Worker w1 WITH (NOLOCK) inner join
dbo.[Contract] WITH (NOLOCK) ON dbo.[Contract].Worker_ID = w1.Worker_ID inner join
dbo.Grade WITH (NOLOCK) ON dbo.Grade.Grade_ID = dbo.[Contract].Grade_ID
WHERE
(dbo.[Contract].StartDate BETWEEN #StartDateF AND #EndDateF AND EndDate IS NULL)
group by
w1.Worker_ID, w1.Title, w1.FirstName, w1.Surname,w1.Gender, w1.DateofBirth,
dbo.[Contract].StartDate, manager, dbo.Grade.Discipline,dbo.Grade.GradeDescription, dbo.[Contract].ContractType_ID
Having DATEDIFF(day, SELECT MAX(StartDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID, SELECT MAX(EndDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID)
I have added the group by and the having clause but now I am getting the following errors
Msg 156, Level 15, State 1, Line 24
Incorrect syntax near the keyword 'SELECT'.
Msg 102, Level 15, State 1, Line 24
Incorrect syntax near ','.
Msg 102, Level 15, State 1, Line 24
Incorrect syntax near ')'.
These all relate the the functions in the having clause no doubt you can see. But I cannot understand what is wrong with this query and this is mainly the question. I need to understand the SQL functions enough so that I can implement th correct solution.
I have followed up the DATEDIFF() function here http://msdn.microsoft.com/en-us/library/ms189794.aspx
I can see that using functions within this function is acceptable according to the MS documentation.
EDIT
Commenting out the Having clause gives me the result set I expect. It is showing people with changes to contracts(pay rise) but this is information that no one should be seeing, these are now the only records that need filtering out
EDIT
I have made some improvements and overcome the error messages now, but I am still getting people where pay rises have occured. Here is the amended query from the group by
group by
w1.Worker_ID, w1.Title, w1.FirstName, w1.Surname,w1.Gender, w1.DateofBirth,
dbo.[Contract].StartDate, manager, dbo.Grade.Discipline,dbo.Grade.GradeDescription, dbo.[Contract].ContractType_ID, w1.Worker_ID
Having
(((dbo.[Contract].StartDate BETWEEN #StartDateF AND #EndDateF)
AND COUNT(dbo.[Contract].Worker_ID) = 1)
OR
((dbo.[Contract].StartDate BETWEEN #StartDateF AND #EndDateF)
AND DATEDIFF(day, (SELECT MAX(EndDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID), (SELECT MAX(StartDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID))>1))
To get workers with more than one contract, you would use:
select c.workerID
from Contract c
group by c.workerID
having count(distinct contractID) > 1
It sounds, though, like you only want to count everything but the new start ones. You can do this with something like:
select w.workerID
from Contract c
where c.ContractType = 'New'
group by w.workerID
having count(distinct contractID) > 1
Because you didn't provide the details of what the tables look like, what sample input data looks like, and the results you want to achieve, this is about the best that can be done.
WHERE ( (dbo.[Contract].StartDate BETWEEN #StartDateF AND #EndDateF)AND dbo.[Contract].Worker_ID
IN (select worker_id from dbo.[Contract]
group by worker_id
having count(worker_id) = 1))
OR
((dbo.[Contract].StartDate BETWEEN #StartDateF AND #EndDateF)
AND DATEDIFF(day, (SELECT MAX(EndDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID), (SELECT MAX(StartDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID))>1
AND dbo.[Contract].Worker_ID = w1.Worker_ID )
Now works for me :)

Resources