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;
Related
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
I have a query as follows
select
Sum(If(departments.vat, If(weeklytransactions.weekendingdate Between
'2011-01-04' And '2099-12-31', weeklytransactions.takings / 1.2,
If(weeklytransactions.weekendingdate Between '2008-11-30' And '2010-01-01',
weeklytransactions.takings / 1.15, weeklytransactions.takings / 1.175)),
weeklytransactions.takings)) As Total,
weeklytransactions.weekendingdate,......
and another that returns a vat rate as follows
select format(Max(Distinct vat_rates.Vat_Rate),3) From vat_rates Where
vat_rates.Vat_From <= '2011-01-03'
I want to replace the hard coded if statement with the lower query, replacing the date in the lower query with weeklytransactions.weekendingdate.
After Kevin's comments, here is the full query I'm trying to get to work;
Select Max(vat_rates.vat_rate) As r,
If(departments.vat, weeklytransactions.takings / r, weeklytransactions.takings) As Total,
weeklytransactions.weekendingdate,
Week(weeklytransactions.weekendingdate),
round(datediff(weekendingdate, (if(month(weekendingdate)>5,concat(year(weekendingdate),'-06-01'),concat(year(weekendingdate)-1,'-06-01'))))/7,0)+1 as fyweek,
cast((Case When Month(weeklytransactions.weekendingdate) >5 Then Concat(Year(weeklytransactions.weekendingdate), '-',Year(weeklytransactions.weekendingdate) + 1) Else Concat(Year(weeklytransactions.weekendingdate) - 1, '-',Year(weeklytransactions.weekendingdate)) End) as char) As fy,
business_units.business_unit
From departments Inner Join (business_units Inner Join weeklytransactions On business_units.buID = weeklytransactions.businessUnit) On departments.deptid = weeklytransactions.departmentId
Where (vat_rates.vat_from <= weeklytransactions.weekendingdate and business_units.Active = true and business_units.sales=1)
Group By weeklytransactions.weekendingdate, business_units.business_unit Order By fy desc, business_unit, fyweek
Regards
Pete
Assuming I read your question correctly, your problem is about having the result of another SELECT used to be returned by the result of your main query (plus depending on how acquainted you are with SQL, maybe you haven't had the occasion to learn about JOINs?).
You can have subqueries you extract data from within a SELECT, provided you define it within the FROMclause. The following query will work, for example:
SELECT A.a, B.b
FROM A
JOIN (SELECT aggregate(c) FROM C) AS B
Notice that there is no reference to table A within the subquery. Thing is, you cannot just add it like that to the query, as the subquery doesn't know it is a subquery. So the following won't work:
SELECT A.a, B.b
FROM A
JOIN (SELECT aggregate(c) FROM C WHERE C.someValue = A.someValue) AS B
Back to basics. What you want to do here visibly, is to aggregate some data associated to each of the records of another table. For that, you will need merge your SELECT queries and use GROUP BY:
SELECT A.a, aggregate(C.c)
FROM A, C
WHERE C.someValue = A.someValue
GROUP BY A.a
Back to your tables, the following should work:
SELECT w.weekendingdate, FORMAT(MAX(v.Vat_Rate, 3)
FROM weeklytransactions AS w, vat_rates AS v
WHERE v.Vat_From <= w.weekendingdate
GROUP BY w.weekendingdate
Feel free to add and remove fields and conditions as you see fit (I wouldn't be surprised that you'd also want to use a lower bound when filtering the records from vat_rates, since the way I have written it above, for a given weekendingdate, you get records from that week + the weeks before!).
So it looks like my first try did not address the actual problem. With the additional information provided in the comments, as well as the new complete query, let's see how this goes.
We are still missing error messages, but normally the query as written should result in MySQL having the following complaint:
ERROR 1109 (42S02): Unknown table 'vat_rates' in field list
Why? Because the vat_rates table does not appear in the FROM clause, whereas it should. Let's make that more obvious by simplifying the query, removing all references to the business_units table as well as the fields, calculations and order that do not add or remove anything to the problem, leaving us with the following:
SELECT MAX(vat_rates.vat_rate) AS r,
IF(d.vat, w.takings / r, w.takings) AS Total
FROM departments AS d
INNER JOIN weeklytransactions AS w ON w.departmentId = d.deptid
WHERE vat_rates.vat_from <= w.weekendingdate
GROUP BY w.weekendingdate
That cannot work, and will produce the error mentioned above. It looks like there is no FOREIGN ID between the weeklytransactions and vat_rates tables, so we have no choice but to do a CROSS JOIN for the moment, hoping that the condition in the WHERE clause and the aggregate function used to get r are enough to fit the business logic at hand here. The following query should return the expected data instead of an error message (I also remove r since that seems to be an intermediate value judging by the comments that were written):
SELECT IF(d.vat, w.takings / MAX(v.vat_rate), w.takings) AS Total
FROM vat_rates AS v, departments AS d
INNER JOIN weeklytransactions AS w ON w.departmentId = d.deptid
WHERE v.vat_from <= w.weekendingdate
GROUP BY w.weekendingdate
From there, assuming it works, you will only need to put back all the parts I removed to get your final query. I am a tad doubtful about the way the VAT rate is gotten here, but I have no idea what your requirements are in that regard so I leave it up to you to make sure that works as expected.
I have the following query:
SELECT routes.route_date, time_slots.name, time_slots.openings, time_slots.appointments
FROM routes
INNER JOIN time_slots ON routes.route_id = time_slots.route_id
WHERE route_date
BETWEEN 20140109
AND 20140115
AND time_slots.openings > time_slots.appointments
ORDER BY route_date, name
This works just fine and will produce the following results:
What I want to do is only return one name per date. So the 9th, name = 1, would only have 1 result, rather than 2, as it currently does.
UPDATE: See the SQLFIDDLE for different type of solutions here: http://sqlfiddle.com/#!2/9ac65b/6
Will it solve your request if you use...
SELECT DISTINCT routes.route_date...your query... ?
It depends if you know that your rows always will have the same values, for same date/name.
Otherwise use group by...
(which I think suits your request best)
SELECT routes.route_date, time_slots.name, sum(time_slots.openings), sum(time_slots.appointments)
FROM routes
INNER JOIN time_slots ON routes.route_id = time_slots.route_id
WHERE route_date
BETWEEN 20140109
AND 20140115
AND time_slots.openings > time_slots.appointments
group by routes.route_date, time_slots.name
ORDER BY route_date, name
(i did a sum for the openings and appointments, you could do min, max, count, etc. Pick the one that fits your requirements best!)
You need to figure out which "name" you want when there are several for the same date.
Then you can group by date and select the right "name" by using an aggregate function like COUNT, MAX, etc.
I can't help you more if you don't explain your rule for picking one.
MySQL Server Version: Server version: 4.1.14
MySQL client version: 3.23.49
Tables under discussion: ads_list and ads_cate.
Table Relationship: ads_cate has many ads_list.
Keyed by: ads_cate.id = ads_list.Category.
I am not sure what is going on here, but I am trying to use COUNT() in a simple agreggate query, and I get blank output.
Here is a simple example, this returns expected results:
$queryCats = "SELECT id, cateName FROM ads_cate ORDER BY cateName";
But if I modify it to add the COUNT() and the other query data I get no array return w/ print_r() (no results)?
$queryCats = "SELECT ads_cate.cateName, ads_list.COUNT(ads_cate.id),
FROM ads_cate INNER JOIN ads_list
ON ads_cate.id = ads_list.category
GROUP BY cateName ORDER BY cateName";
Ultimately, I am trying to get a count of ad_list items in each category.
Is there a MySQL version conflict on what I am trying to do here?
NOTE: I spent some time breaking this down, item by item and the COUNT() seems to cause the array() to disappear. And the the JOIN seemed to do the same thing... It does not help I am developing this on a Yahoo server with no access to the php or mysql error settings.
I think your COUNT syntax is wrong. It should be:
COUNT(ads_cate.id)
or
COUNT(ads_list.id)
depending on what you are counting.
Count is an aggregate. means ever return result set at least one
here you be try count ads_list.id not null but that wrong. how say Myke Count(ads_cate.id) or Count(ads_list.id) is better approach
you have inner join ads_cate.id = ads_list.category so Count(ads_cate.id) or COUNT(ads_list.id) is not necessary just count(*)
now if you dont want null add having
only match
SELECT ads_cate.cateName, COUNT(*),
FROM ads_cate INNER JOIN ads_list
ON ads_cate.id = ads_list.category
GROUP BY cateName
having not count(*) is null
ORDER BY cateName
all
SELECT ads_cate.cateName, IFNULL(COUNT(*),0),
FROM ads_cate LEFT JOIN ads_list
ON ads_cate.id = ads_list.category
GROUP BY cateName
ORDER BY cateName
Did you try:
$queryCats = "SELECT ads_cate.cateName, COUNT(ads_cate.id)
FROM ads_cate
JOIN ads_list ON ads_cate.id = ads_list.category
GROUP BY ads_cate.cateName";
I am guessing that you need the category to be in the list, in that case the query here should work. Try it without the ORDER BY first.
You were probably getting errors. Check your server logs.
Also, see what happens when you try this:
SELECT COUNT(*), category
FROM ads_list
GROUP BY category
Your array is empty or disappear because your query has errors:
there should be no comma before the FROM
the "ads_list." prefix before COUNT is incorrect
Please try running that query directly in MySQL and you'll see the errors. Or try echoing the output using mysql_error().
Now, some other points related to your query:
there is no need to do ORDER BY because GROUP BY by default sorts on the grouped column
you are doing a count on the wrong column that will always give you 1
Perhaps you are trying to retrieve the count of ads_list per ads_cate? This might be your query then:
SELECT `ads_cate`.`cateName`, COUNT(`ads_list`.`category`) `cnt_ads_list`
FROM `ads_cate`
INNER JOIN `ads_list` ON `ads_cate`.`id` = `ads_list`.`category`
GROUP BY `cateName`;
Hope it helps?
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).