I am looking for some help with the following query. The results I get back are fine as long as there is data in the ShiftData table that meets the criteria. If there is no data in the ShiftDaa table then my query returns nothing. What I am after is to return back all LoopCodes and Choppers from MapBushingData table and zeros if there are no items in ShiftData table matching the criterion. Any help is most appreciated.
Sum(ShiftData.BRKS) AS Total_BRKS,
Sum(ShiftData.BBOH) AS Total_BBOH,
Avg(ShiftData.DTAB) AS Avg_DTAB
INNER JOIN MapBushingData ON ShiftData.[Position] = MapBushingData.LoopCode WHERE ShiftData.ShiftDate >= cast(? as date) AND ShiftData.ShiftDate <= cast(? as date)
GROUP BY MapBushingData.Chopper,MapBushingData.LoopCode
Using an INNER JOIN requires matching record to be in both tables.
To get all records from one table regardless if it matches or not you would use either a LEFTRIGHT JOIN. As you want all the records from the second table in the ON connector it would be a RIGHT JOIN
The second thing is dealing with returning 0 if no records match. Relatively easy, just slap an ISNULL(or COALESCE for ANSI SQL) with 0 as the null replacement.
My first attempt at this came up with
, Total_BRKS = IsNull(Sum(s.BRKS), 0)
, Total_BBOH = IsNull(Sum(s.BBOH), 0)
, Avg_DTAB = IsNull(Avg(s.DTAB), 0)
RIGHTJOIN@MapBushingData m ON s.[Position] = m.LoopCode
WHERE ( s.ShiftDate >= cast('02/03/2011'asdate)
AND s.ShiftDate <= cast('03/04/2013'asdate)
OR s.ShiftDate ISNULLGROUPBY m.Chopper,m.LoopCode
And in testing I found out that IF there is a matched record BUT the date was out of range it would not return the record.
If this is desired; great.
If not, we are going to tweak how the data is JOINed together by relocating the WHERE clauses to also be part of the JOIN connections. And this is what I came up with
First of all sorry for putting like a code dump here... I'll try to explain it as clearly as possible, but given my inexperience with SQL (years and years without touching it) I think it is better if I post the two queries completely rather than asking a generic question.
I have two SQL queries that work well.
I need to mix them and I don't know how to do it.
The first one returns me all the details of the Invoice and the customer name, and the second one gives me the invoice cost after making the right selections and calculations (more on this after).
SELECT tInvoices.*, tCustomers.name FROM tInvoices INNERJOIN tCustomers ON CustomerId = tCustomers.id;
That way I get all the invoice details and the customer name in each row to show it in an HTML table.
But I also want to put the invoice price in that table and this is much more complicated:
I have a structure in which there is a reference price per customer, project and user... this means that depending on what's agreed with each customer for each project, each user will have a cost...
If I go to a customer company to program something I could get X€ and other guy from the company could get Y€. And those proces could be V€ and W€ for another project for the same customer...
Appart of that I've set in each task a special cost field. If that cost is filled (not NULL) then I'll use that cost as an exception (again something pacted with the customer).
All this said... this happens with the tasks (work done in a project by a human being) and with the expenses (hotel, gasoline, meals... tickets in general).
And the second query is not that simple, but seems to work well:
SELECT SUM(subTotal) AS total FROM
CASEWHEN tTasks.taskUseId = 1THEN
CASEWHEN price ISNULLTHEN
WHERE tReferencePricesForTasks.taskTypeId = tTasks.taskTypeId AND
tReferencePricesForTasks.projectId = tTasks.projectId AND
tReferencePricesForTasks.userId = tTasks.userId
ROUND(TIME_TO_SEC(TIMEDIFF(endTime, startTime)) / 3600,2)
LEFTJOIN tTasksTypes ON tTasks.taskTypeId = tTasksTypes.id
WHERE tTasks.taskUseId <> 3AND
tTasks.invoiceId = '.$PHP_Invoice_ID_VALUE.'UNIONALLSELECT
CASEWHEN price ISNULLTHEN
WHERE tReferencePricesForExpenses.expenseTypeId = tExpenses.expenseTypeId AND
tReferencePricesForExpenses.projectId = tExpenses.projectId AND
tReferencePricesForExpenses.userId = tExpenses.userId
LEFTJOIN tExpensesTypes ON tExpenses.expenseTypeId = tExpensesTypes.id
WHERE tExpenses.invoiceId = '.$PHP_Invoice_ID_VALUE.'
As you can see in my second query, I'm using $PHP_Invoice_ID_VALUE which is a PHP variable that I update in each row of the first query to get the Invoice ID.
I'd like to mix both queries, but I don't know how to do it.
The idea is not needing to call the second query in each row... that way everything should be faster and I would be able to apply filters and orders given the price too...
I would like to substitute the PHP variables for each invoice listed in the first query.
Using Mysql and MariaDB.
Sorry for the code dump, but I truly don't know how to ask it generically without missing any detail.
First of all, thank you very much for your answer!
I've seen the CTE concept in the Internet... it would make this a little bit easier... the problem is that PHPMyAdmin doesn't like the clause "WITH" and therefore I can't test it...
I'm thinking of storing the total price value into a new column of the invoice table and recalculate it after creating it or each time I modify it... It probably will be much faster when getting all the data and I can't see why it would be a bad design... but I'm super novice... Would it be something terrible?
And I'm curious... why would you look at the roundings?
I'm trying to avoid the need to do two queries while populating a table...
Would it be a bad design to add that totalInvoicePrice into the table tInvoices? that way at the moment of creating the invoice I would do what it's working now... and when I would need to get the data it would be extremely easy...