MySQL: Value of child lines based on proportion of cost? - mysql

We have a packslip lines table with the following structure (simplified):
line_id (unique id for packslip line)
sku (item #)
name
weight
value (value/price of item)
cost
is_kit (is this a kit/parent item?)
parent_line_id (if it's a child item, will contain line_id of parent)
A packslip line can represent an individual product, a parent kit, or kit components. For this exercise, use the following data set:
1, 'ITEM1', 'Item # 1', 0.3, 9.99, 4.79, 0, null
2, 'KIT1', 'Kit # 1', 1.3, 29.99, 0, 1, null
3, 'KITITEM1', 'Kit Item # 1', 0.7, 0, 10.0, 0, 2
4, 'KITITEM2', 'Kit Item # 2', 0.3, 0, 2.49, 0, 2
5, 'KITITEM3', 'Kit Item # 3', 0.3, 0, 4.29, 0, 2
As you can hopefully see, ITEM1 is a regular/individual product, KIT1 is a parent kit, and the last 3 items are child components for KIT1.
Notice that the kit lacks a cost and that the kit items lack a value. I need to create a query that will calculate the kit item values based on the proportion of the items' costs to the overall cost of the kit.
So in this example:
KITITEM1 Value = 10 / (10.0 + 2.49 + 4.29) * 29.99 = $17.87
KITITEM2 Value = 2.49 / (10.0 + 2.49 + 4.29) * 29.99 = $4.45
KITITEM3 Value = 4.29 / (10.0 + 2.49 + 4.29) * 29.99 = $7.67
Can I accomplish this in a single query (can have nested queries)? How?

try this query, sqlFiddle
SELECT T1.line_id,
T1.sku,
T1.name,
T1.weight,
IF (T1.parent_line_id IS NULL,T1.value,
ROUND(T1.cost * T2.value_divided_by_total_cost,2))as value,
T1.cost,
T1.is_kit,
T1.parent_line_id
FROM packslip T1
LEFT JOIN
(SELECT parent_line_id,(SELECT value FROM
packslip p2 WHERE p1.parent_line_id = p2.line_id)
/SUM(cost)
as value_divided_by_total_cost
FROM packslip p1
WHERE parent_line_id IS NOT NULL
GROUP BY parent_line_id
)T2
ON T1.parent_line_id = T2.parent_line_id
The query LEFT JOIN with a derived table that gets the (value of parent) divided by SUM(cost) GROUP BY that parent.
Then the outer query checks to see if parent_line_id IS NOT NULL and multiplies the cost by value from the derived table.

Related

How to fix 'subquery returns more than 1 row' with variable tables

I have a table RAW_SCORES that contains a bunch of homework/exam grades. There is a row in RAW_SCORES that contains the max points for each assignment.
('6410', 'Rivera', 'Rhonda', '315', 64, 64, 28, 85, 98, 152),
('0001', 'MAX', 'POINTS', '415', 100, 80, 32, 100, 120, 200),
I want to create a procedure that prints a table with the (Raw Score / Max Score) for each assignment. So for assignment 1:
SET hw1M = (SELECT HW1 FROM RAW_SCORES WHERE (SSN = '0001'));
SELECT RAW_SCORES.SSN,
RAW_SCORES.FName,
RAW_SCORES.LName,
ROUND(RAW_SCORES.HW1 / hw1M, 2)
FROM RAW_SCORES WHERE NOT (RAW_SCORES.SSN = '0001' OR RAW_SCORES.SSN = '0002');
Gives me the correct result for HW1, but the table header says Round(bla bla bla) and the question wants it to be printed as HW1Pct. So I tried:
SET hw1M = (SELECT HW1 FROM RAW_SCORES WHERE (SSN = '0001'));
SET HW1Pct = (SELECT ROUND(RAW_SCORES.HW1 / hw1M, 2) FROM RAW_SCORES WHERE hw1M IN (SELECT HW1 FROM RAW_SCORES WHERE (SSN = '0001')));
SELECT RAW_SCORES.SSN,
RAW_SCORES.FName,
RAW_SCORES.LName,
HW1Pct
FROM RAW_SCORES WHERE NOT (RAW_SCORES.SSN = '0001' OR RAW_SCORES.SSN = '0002');
But this gives me the Subquery returns more than 1 row error. Most of the other answers to this error are a JOIN statement, but I'm not sure how I would implement that in my case. Any help is appreciated. Sorry for it being a dumb question.
Just add a column alias to your original query:
ROUND(RAW_SCORES.HW1 / hw1M, 2) AS HW1Pct
See the manual

SSRS Case Statement

I have created a table in SSRS of various grades, but I need to look at the value of 2 grades together and assign it an alternate grade. I cannot put this as a CASE in the SELECT as the way the database is designed the values are not stored in one row, but in multiple rows, therefore it cannot combine the data in a new column. For example, this is one students grades represented in the DB
634 Attainment *#1#2#3#4#N/A NULL 1 2
636 Effort A*#A#B#C#N/A NULL A 2
637 Focus EX#ME#WB#N/A NULL EX 1
638 Participation EX#ME#WB#N/A NULL ME 2
639 Groupwork EX#ME#WB#N/A NULL ME 2
640 Rigour EX#ME#WB#N/A NULL ME 2
641 Curiosity EX#ME#WB#N/A NULL ME 2
642 Initiative EX#ME#WB#N/A NULL ME 2
643 Self Organisation EX#ME#WB#N/A NULL ME 2
644 Perseverance EX#ME#WB#N/A NULL ME 2
I have created a table that has grouped the grades based on the pupil ID and it is now represented as one row and column headings for each grade (effort, Focus etc).
I have tried to do a sum using the ReportItems!Textbox1.Value but I can't use this method as it is not an aggregate function. What I wanted to do was
IF (ReportItems!Textbox104.Value + ReportItems!Textbox105.Value = 2) THEN 5
Is there a way to do this?
ADDITIONAL:
I have just tried:
=SWITCH(ReportItems!Textbox104.Value + ReportItems!Textbox105.Value = 2, 5,
ReportItems!Textbox104.Value + ReportItems!Textbox105.Value = 3, 4,
ReportItems!Textbox104.Value + ReportItems!Textbox105.Value = 4, 3,
ReportItems!Textbox104.Value + ReportItems!Textbox105.Value = 5, 2,
ReportItems!Textbox104.Value + ReportItems!Textbox105.Value = 6, 1,
ReportItems!Textbox104.Value + ReportItems!Textbox105.Value = 7, 0,
"NULL"
)
This is returning an Error.
I finally resolved this by using this expression:
=IIF(ReportItems!Textbox104.Value + (ReportItems!Textbox105.Value = 2), 5,
IIF(ReportItems!Textbox104.Value + (ReportItems!Textbox105.Value = 3), 4,
IIF(ReportItems!Textbox104.Value + (ReportItems!Textbox105.Value = 4), 3,
IIF(ReportItems!Textbox104.Value + (ReportItems!Textbox105.Value = 5), 2,
IIF(ReportItems!Textbox104.Value + (ReportItems!Textbox105.Value = 6), 1,
IIF(ReportItems!Textbox104.Value + ReportItems!Textbox105.Value = 7, 0,
"NULL"))))))

sql/mysql Multiple results from one value

I am working on an integration output report to feed into a purchase order system.
All of the possible items are straightforward except for one particular item, which has to be broke out into multiple components.
The current code:
select concat("M", id) as ID, MaterialId, quantity, uom,
crew_job.JobSubNbr, crew_job.EmployeeId, crewjob_schedule_actual.startTime
from crewjob_material_actual
inner join crew_job on crewjob_material_actual.crew_job_id = crew_job.crew_job_id
inner join crewjob_schedule_actual on
crewjob_material_actual.crew_job_id = crewjob_schedule_actual.crew_job_id
And the current results output:
What I need to do is something of the effect of (and this is in plain English)
IF "MaterialID" = '3'
THEN [the results should be] show me 3 rows of data such as:
ID = MZ4931, MaterialID = 100, Qty = 0.25, UOM = 1 .... (all else the
same) ID = MZ4932, MaterialID = 101, Qty = 0.50, UOM = 1 .... (all
else the same) ID = MZ4933, MaterialID = 102, Qty = 0.33, UOM = 2
.... (all else the same)
Essential, item #3 is a "combined item" that I need to apply based on a standard ratio, where 1 unit of Item 3 is equal to .25 of item 100, .50 of item 101, and 0.33 of item 102. I'm sure this isn't too difficult but I was having a hard time searching.

Fastest way to calculate correlation in every row?

Well, I have a table data of millions of rows. I want to carry out correlation study for every row (from the 1st to the current row minus 1). For e.g. the 1st rows is omitted. The 2nd row's result column is to be supplied with the correlation using the 1st row. The 3rd row's result column is to be supplied with the correlation using the 1st and 2nd row. And so on.
Correlation for the entire table can be calculated using:
SELECT (Count(*)*Sum(x*y)-Sum(x)*Sum(y))/
(sqrt(Count(*)*Sum(x*x)-Sum(x)*Sum(x))*
sqrt(Count(*)*Sum(y*y)-Sum(y)*Sum(y))) AS TotalCorelation FROM Data;
I want to avoid using Joins as much as possible as it takes lots of time, sometimes even timeout error, above 300 seconds). What's the other alternative?
Example table Data Structure:
id, x, y, result
1 , 4, 2, null
2 , 6, 3, -0.2312
3 , 5, 5, 0.42312
4 , 6, 2, -0.5231
5 , 5, 5, 0.22312
6 , 3, 7, -0.2312
7 , 2, 9, 0.42231
8 , 7, 2, 0.32253
9 , 9, 5, 0.32431
id : primary key
x and y : The data
result: correlation
I think this is it:
SELECT d2.ID, d2.x, d2.y, d2.result,
(Count(*)*Sum(d1.x*d1.y)-Sum(d1.x)*Sum(d1.y))/
(sqrt(Count(*)*Sum(d1.x*d1.x)-Sum(d1.x)*Sum(d1.x))*
sqrt(Count(*)*Sum(d1.y*d1.y)-Sum(d1.y)*Sum(d1.y))) AS TotalCorelation
FROM Data d1
RIGHT JOIN Data d2 ON d1.id < d2.id
GROUP BY d2.ID
ORDER BY d2.ID
Without a closed form for calculating correlation of N+1 from N rows, you have to use a quadratic join like this.
I'm assuming that your basic formula is correct. But I'm not sure it is -- when I just run it on the total dataset, I don't get the result 0.32431, I get -0.552773693079.
Here's a linear implementation:
SET #SumX = 0;
SET #SumY = 0;
SET #Count = 0;
SET #SumX2 = 0;
SET #SumY2 = 0;
SET #SumXY = 0;
SELECT id, x, y,
#SumX := #SumX + x AS SumX,
#SumY := #SumY + y AS SumY,
#Count := #Count + 1 AS ct,
#SumX2 := #SumX2 + x*x AS SumX2,
#SumY2 := #SumY2 + y*y AS SumY2,
#SumXY := #SumXY + x*y AS SumXY,
IF(#Count > 1,
(#Count*#SumXY-#SumX*#SumY)/
(sqrt(#Count*#SumX2-#SumX*#SumX)*
sqrt(#Count*#SumY2-#SumY*#SumY)), NULL) AS TotalCorelation
FROM DATA
ORDER BY id
SQLFIDDLE

How to get an ordered list of rows within 0 value with sql?

For example:
SELECT * FROM atable ORDER BY num;
'atable' is:
num name
1 a
3 y
0 cc
2 fs
The result is:
num name
1 a
2 fs
3 y
0 cc
But I want it to be:
num name
0 cc
1 a
2 fs
3 y
I can't reproduce the result you are seeing. The query that you posted should work as you wish it to. Here's my steps to reproduce:
CREATE TABLE atable (num INT NOT NULL, name NVARCHAR(100) NOT NULL);
INSERT INTO atable (num, name) VALUES
(1, 'a'),
(3, 'y'),
(0, 'cc'),
(2, 'fs');
SELECT * FROM atable ORDER BY num;
Result:
0, 'cc'
1, 'a'
2, 'fs'
3, 'y'
Perhaps you could post your create scripts for your table and test data in your question so that we can reproduce your result?
Are you sure that the 0 isn't a null value being displayed as a 0? Nulls can sort either at the top or the bottom, depending on database setting.
SELECT * FROM atable
ORDER BY ISNULL(CAST(num as int), 0);