Is this a legal SQL query? - mysql

I have a schema like this
...
Event(Name, Date, TotalSeats)
Reservation(EventName, Date, NumSeats)
...
I want to extract the total number of seats available for each event, is the following query a legal way to do it?
SELECT R.EventName, (SELECT TotalSeats
FROM Event
WHERE Name = R.EventName) - SUM( NumSeats )
FROM Reservation R
GROUP BY EventName;

The more traditional way to write this query would use join:
SELECT r.EventName, e.TotalSeats - SUM( r.NumSeats )
FROM Reservation r JOIN
Event e
ON e.Name = r.EventName
GROUP BY r.EventName, e.TotalSeats;
Your version should work in MySQL, assuming there are no duplicates in the Event table.

The query which you have written in your sub-query..
SELECT TotalSeats FROM Event WHERE Name = R.EventName
can consist of more than one records.. so in that case this query will return error..

Related

Retrieve customer revenue

I want to create a report with the top 20 customers (based on revenue).
I am using the query:
SELECT dbo.CustTable.AccountNum
,dbo.dirpartytable.NAME
,dbo.hcmworker.PERSONNELNUMBER
,dbo.CustInvoiceJour.SALESBALANCE
,dbo.custinvoicejour.QTY
FROM dbo.CustTable
inner JOIN dbo.HCMWORKER ON dbo.HCMWORKER.RECID = dbo.CustTable.KEV_Worker
inner join dbo.custInvoiceJour on CustInvoiceJour.OrderAccount = CustTable.AccountNum
inner join dbo.dirpartytable on dirpartytable.recid = custtable.PARTY
where CustTable.KEV_Worker = '5633561745'
ORDER BY SalesBalanceMst DESC
I can't find the relation for the customer revenue, after all, that is how I want to sort the report. I am sorting on SalesBalanceMST right now while building the report. Also I am getting multiple records when executing this query.
What am i doing wrong?
EDIT: I now realize I am showing each Invoice Journal, how can I display the Total Revenue of the customer?
A similar search from AX 2012:
CustInvoiceJour CustInvoiceJour;
CustTable CustTable;
DirPartyTable DirPartyTable;
select forceLiterals generateonly sum(SalesBalanceMST), sum(Qty) from CustInvoiceJour
where CustInvoiceJour.OrderAccount == '102372200'
&& CustInvoiceJour.InvoiceDate > today()-365
join TableId from CustTable
group AccountNum
where CustTable.AccountNum == CustInvoiceJour.OrderAccount
join TableId from DirPartyTable
group Name
where DirPartyTable.RecId == CustTable.Party;
info(CustInvoiceJour.getSQLStatement());
This shows the following SQL:
SELECT SUM(T1.SALESBALANCEMST),SUM(T1.QTY),T2.ACCOUNTNUM,T3.NAME
FROM CUSTINVOICEJOUR T1
CROSS JOIN CUSTTABLE T2
CROSS JOIN DIRPARTYTABLE T3
WHERE (((T1.PARTITION=5637144576) AND (T1.DATAAREAID=N'xxx'))
AND ((T1.ORDERACCOUNT=N'102372200')
AND (T1.INVOICEDATE>{ts '2015-11-06 00:00:00.000'})))
AND (((T2.PARTITION=5637144576) AND (T2.DATAAREAID=N'xxx'))
AND (T2.ACCOUNTNUM=T1.ORDERACCOUNT))
AND ((T3.PARTITION=5637144576)
AND (T3.RECID=T2.PARTY))
GROUP BY T2.ACCOUNTNUM,T3.NAME
ORDER BY T2.ACCOUNTNUM,T3.NAME
What is different from your query:
no join on HcmWorker, as I do not have your custom field.
Using sum() to aggregate
selecting on InvoiceDate
selection on OrderAccount
selection on DataAreaId, really important for performance, implicit in AX
selection on Partition, really important for performance, implicit in AX
You cannot directly sort on a sum, but may on a nested SQL query.
I do not know exactly what is wrong in your query but perhaps this information can help you.
Check this standard report CustTopCustomersbyYTDSales, It has some good queries to do that.
https://technet.microsoft.com/en-us/library/hh389751.aspx

Using MAX() in sub query without GROUP BY

I'm doing pratice work for a class and I have the following schema to work with:
Project (Projectid, Milestoneid, dateBegin, dateEnd)
Milestone (Milestoneid, MilestoneName, MilestoneDesc)
I need to output the Projectid, with the Milestonename and Milestonedesc of the latest milestone for each project (latest milestone for each project is the highest Milestoneid for a given projectid)
I was given the following clues: "You want to find Max value of Milestoneid. you must not use GROUP BY."
I know I have to use the MAX aggregate, but I must not use 'GROUP BY', which is where I'm lost.
Obviously I have to use MAX in a subquery, for something like this:
SELECT Project.Projectid, Milestone.Milestonename, Milestone.Milestonedesc
FROM Project p, Milestone m
WHERE m.Milestoneid = (
SELECT MAX(m.Milestoneid)
FROM Milestone m
WHERE
)
I'm at a loss as to how query the table to get a MAX id for each Projectid without group by.
If anyone has any pointers it would greatly help me understand this part of SQL I'm unfamiliar with.
Thanks
A small tweak to your query offers another solution. The request says not to use group by, but you can have a correlated subquery without group by:
SELECT p.Projectid, m.Milestonename, m.Milestonedesc
FROM Project p JOIN
Milestone m
p.Milestoneid = m.Milestoneid
WHERE m.Milestoneid = (SELECT MAX(p2.Milestoneid)
FROM Project p2
WHERE p2.ProjectId = p.ProjectId
)
I suspect that the MAX keyword is a red herring. Anyway, here's one solution (incomplete)...
SELECT x.*
FROM project x
LEFT
JOIN project y
ON y.project_id = x.project_id
-- any other JOINs go here
AND y.milestoneid < x.milestoneid
WHERE y.projectid IS NULL
-- any other conditions go here;

MS Access query multiple criteria

I am trying to build an access query with multiple criteria. The table to be queried is "tblVendor" which has information about vendor shipment data as shown below:
The second table is "tblSchedule" which has the schedule for each Vendor cutoff date. This table has cutoff dates for data analysis.
For each vendor, I need to select records which have the ShipDate >= CutoffDate. Although not shown in the data here, it may be possible that multiple vendors have same CutoffDate.
For small number of records in "tblCutoffdate", I can write a query which looks like:
SELECT tblVendors.ShipmentId, tblVendors.VendorNumber, tblVendors.VendorName,
tblVendors.Units, tblVendors.ShipDate
FROM tblVendors INNER JOIN tblCutoffDate ON tblVendors.VendorNumber =
tblCutoffDate.VendorNumber
WHERE (((tblVendors.VendorNumber) In (SELECT VendorNumber FROM [tblCutoffDate] WHERE
[tblCutoffDate].[CutoffDate] = #2/1/2014#)) AND ((tblVendors.ShipDate)>=#2/1/2014#)) OR
(((tblVendors.VendorNumber) In (SELECT VendorNumber FROM [tblCutoffDate] WHERE
[tblCutoffDate].[CutoffDate] = #4/1/2014#)) AND ((tblVendors.ShipDate)>=#4/1/2014#));
As desired, the query gives me a result which looks like:
What concerns me now is that I have a lot of records being added to the "tblCutoffDate" which makes it difficult for me to hardcode the dates in the query. Is there a better way to write the above SQL statement without any hardcoding?
You might try something like -- this should handle vendors having no past cutoff,
or those having no future cutoff
"today" needs a suitable conversion to just date w/o time
comparison "=" may go on both, or one, or none Max/Min
"null" may be replaced by 1/1/1900 and 12/31/3999 in Max/Min
SELECT tblvendors.shipmentid,
tblvendors.vendornumber,
tblvendors.vendorname,
tblvendors.units,
tblvendors.shipdate
FROM tblvendors
LEFT JOIN
( SELECT vendornum,
Max( iif cutoffdate < today, cutoffdate, null) as PriorCutoff,
Min( iif cutoffdate >= today, cutoffdate, null) as NextCutoff
FROM tblcutoffdate
GROUP BY vendornum
) as VDates
ON vendornumber = vendornum
WHERE tblvendors.shipdate BETWEEN PriorCutoff and NextCutoff
ORDER BY vendornumber, shipdate, shipmentid
A simpler WHERE clause should give you what you want.
SELECT
v.ShipmentId,
v.VendorNumber,
v.VendorName,
v.Units,
v.ShipDate
FROM
tblVendors AS v
INNER JOIN tblCutoffDate AS cd
ON v.VendorNumber = cd.VendorNumber
WHERE v.ShipDate >= cd.CutoffDate;

Query to sum some of the values

Ive got a simple query that is used on a search. My problem is with this query is that as the records in mysql are added everytime there is a transaction, the query returns a list of data when there could only be one or a few more rows instead of a lot more.
SQLFliddle
As you can see here - the query returns a lot of rows, where I want it to return
BLSH103 A001A 31 24/01/2014
Can the qty where the product name & pallet space are the same be summed? And then show the largest date?
just use a sum function on t.Quantity (and a group by clause)
SELECT (t.ProductName) as Pname ,(s.PalletSpace) as PSpace, sum(t.Quantity) as Qty,(t.TransactionDate) as Transac
FROM PalletSpaces s
JOIN ProductTrans t
ON s.PalletSpaceID = t.PalletSpace
WHERE t.ProductName LIKE 'BLSH103' OR s.PalletSpace LIKE 'BLSH103'
group by
Pname,
pSpace,
Transac -- if you want to group by date also...
By the way, using LIKE this way (without %) doesn't make much sense...
see SqlFiddle
You just need to use GROUP BY and SUM in this way:
SELECT (t.ProductName) as Pname ,(s.PalletSpace) as PSpace, SUM(t.Quantity) as Qty,(t.TransactionDate) as Transac
FROM PalletSpaces s
JOIN ProductTrans t
ON s.PalletSpaceID = t.PalletSpace
WHERE t.ProductName LIKE 'BLSH103' OR s.PalletSpace LIKE 'BLSH103'
GROUP BY t.ProductName, s.PalletSpace;

Converting a SQL query with group by into LINQ query

I'm stuggling to replicate a SQL query into LINQ.
Can any one help?
SQL:
SELECT tblInvoice.lngID AS InvoiceID,
tblInvoice.dtTimeStamp AS InvoiceDate,
tblInvoice.strReference,
tblInvoice.fltTotalValue,
max(Project.ProjectID) AS ProjectID,
max(Project.ProjectName) AS ProjectName,
max(Project.Location) AS ProjectLocation
FROM tblInvoice INNER JOIN
tblInvoiceLine ON tblInvoice.lngID = tblInvoiceLine.lngInvoiceID
WHERE (tblInvoice.intStatus != 0)
AND (tblInvoice.lngPersonID = #PersonID)
GROUP BY tblInvoice.lngID, tblInvoice.dtTimeStamp, strReference, fltTotalValue
ORDER BY tblInvoice.lngID DESC
LINQ so far:
var invoices = from inv in db.TblInvoices
join invLine in db.TblInvoiceLines on inv.LngID equals invLine.LngInvoiceID
where inv.IntStatus != 0
where inv.LngPersonID == personID
group inv by new {inv.LngID,inv.DtTimeStamp,inv.StrReference,inv.FltTotalValue} into newInv
Part of the problem is that I want to do a
select new Invoice(){
}
and build up my custom Invoice object but, I cant see any of the properties in newInv.
Can any one advise?
I don't have time for a full answer now, but:
To get at properties of the key, use newInv.Key.StrReference etc
To get at aggregates (e.g. max values) use newInv.Max(x => x.ProjectId) etc
Hopefully that'll be enough to get you going. Basically, newInv will be a group of entries, with an associated key (which is what you grouped by).