MySQL Column that shows order of items - mysql

I'm new to MySQL procedures and triggers and constraints and I'm wondering how I can set one of my columns to be dependent on another column. For example, I have a table of products and weekly sales similar to:
Product_ID Sales Ranking
1 13
2 12
3 543
4 435
5 97
I want my ranking column to be automatically updated whenever a value in the sales is updated or a new value is inserted (this table will only hold at most 50 products), which means product IDs will come and go. How can I set it so that the Ranking is always an x value such that x represents what position it would be it the product id was ordered by sales DESC?
Product ID is NOT an AI column or Primary Index

Related

How to update a column by subtracting from another table?

I have two tables cart and cages, I am trying to update the 'remaining' column by checking the item_name for all entries in cart and subtracting the quantity in the corresponding tables.
[cages]
id name total remaining
-----------------------------------
1 Cage1 10 10
2 Cage2 15 15
3 Cage3 10 10
[cart]
id item_name quantity
-----------------------------------
1 Cage1 2
2 Book4 3
There are several tables in the database that would need to be checked upon purchase however, I am not sure what would be the best way of performing these queries without joining all tables. This is the query I have been attempting to use.
UPDATE cages
SET remaining = (remaining - cart.quantity
WHERE cart.item_name = cages.name);
You must join the tables before you can update
UPDATE cages
JOIN cart on cart.item_name = cages.name
SET remaining = (remaining - cart.quantity)

Trying to create a trigger to update Sum Table

I am new to triggers and have an idea that may speed up my query.
I have a table called labour, which has Id (Primary Key, AI), Job_No, Date, Paying_Rate and Working_Hrs
I have a table called Sum which has Id (Primary Key, AI), Job_No and Total_Labour
So when a new line gets added to labour or updated, I want it to insert the sum into the Sum table.
So I am thinking along these lines.
When labour added Select Sum (Paying_Rate*Working_Hrs)AS Sum, then insert that into the sum table, Total_Labour as per Job_No.
Then when another new labour is added, with the same Job_No the same query runs, but it updates the Total_Labour in the Sum table.
Looking at it like a table view.
Labour
Id
Job_No
Date
Paying_Rate
Working_Hrs
Calculated AS Sum
1
1000
10.00
10
100.00
2
1000
20.00
4
80.00
Sum
Id
Job_No
Total_Labour
1
1000
180.00
Is what I am trying possible?
Thank you

Spotfire intersect first 'n' periods

Is there a way to use an Over and Intersect function to get the average sales for the first 3 periods (not always consecutive months, sometimes a month is skipped) for each Employee?
For example:
EmpID 1 is 71.67 ((80 + 60 + 75)/3) despite skipping "3/1/2007"
EmpID 3 is 250 ((350 + 250 + 150)/3).
I'm not sure how EmpID 2 would work because there are just two data points.
I've used a work-around by calculated column using DenseRank over Date, "asc", EmpID and then used another Boolean calculated column where DenseRank column name is <= 3, then used Over functions over the Boolean=TRUE column but I want to figure the correct way to do this.
There are Last 'n' Period functions but I haven't seen anything resembling a First 'n' Period function.
EmpID Date Sales
1 1/1/2007 80
1 2/1/2007 60
1 4/1/2007 75
1 5/1/2007 30
1 9/1/2007 100
2 2/1/2007 200
2 3/1/2007 100
3 12/1/2006 350
3 1/1/2007 250
3 3/1/2007 150
3 4/1/2007 275
3 8/1/2007 375
3 9/1/2007 475
3 10/1/2007 300
3 12/1/2007 200
I suppose the solution depends on where you want this data represented, but here is one example
If((Rank([Date],"asc",[EmpID])<=3) and (Max(Rank([Date],"asc",[EmpID])) OVER ([EmpID])>=3),Avg([Sales]) over ([EmpID]))
You can insert this as a calculated column and it will give you what you want (assuming your data is sorted by date when imported).
You may want to see the row numbering, and in that case insert this as a calculated column as well and name it RN
Rank([Date],"asc",[EmpID])
Explanation
Rank([Date],"asc",[EmpID])
This part of the function is basically applying a row number (labeled as RN in the results below) to each EmpID grouping.
Rank([Date],"asc",[EmpID])<=3
This is how we are taking the top 3 rows regardless if Months are skipped. If your data isn't sorted, we'd have to create one additional calculated column but the same logic applies.
(Max(Rank([Date],"asc",[EmpID])) OVER ([EmpID])>=3)
This is where we are basically ignoring EmpID = 2, or any EmpID who doesn't have at least 3 rows. Removing this would give you the average (dynamically) for each EmpID based on their first 1, 2, or 3 months respectively.
Avg([Sales]) over ([EmpID])
Now that our data is limited to the rows we care about, just take the average for each EmpID.
#Chris- Here is the solution I came up with
Step 1: Inserted a calculated column 'rank' with the expression below
DenseRank([Date],"asc",[EmpID])
Step 2: Created a cross table visualization from the data table and limited data with the expression below

SSIS fuzzy lookup (lookup agains valid range of values)

I was wondering if anyone had a good solution to trying lookup a value against a range of values in a fuzzy lookup transformation.
By "range of values" I mean either a date range such as start and end dates in the lookup table or comparison range such as a high and low value of house numbers compared to the exact house number in a record.
Or if there is solution how to solve fuzzy lookup against only valid values by condtion.
Iam using ssis 2008
Example:
My sales data example:
ID Product Quatity date
1 Product1 1 1.2.2015
2 Produc?t1 1 1.2.2015
3 Produt1_ 1 10.7.2015
My price list
ID Name Price ValidFrom ValidTO
1 Product1 10 1.1.2015 28.2.2015
2 Product1 11 1.3.2015 null
My sales data are kind of dirty (sources are various) - that's why I want to use FUZZY lookup.
I want to fuzzky lookup againts my price list but only against valid prices.
So after lookup result should look like this
ID Product Quatity date Price
1 Product1 1 1.2.2015 10
2 Produc?t1 1 1.2.2015 10
3 Produt1_ 1 10.7.2015 11
But if I use fuzzy I cannot specify the condition before I use fuzzy lookup.
Thanks in advance,
Martin

Please explain the functionality of select max(...) ... group by in sql

I appreciate that this may appear to many as a dum question but I cannot find a clear explanation anywhere as to what the effect of "group by" has on a select max(...) from SQL statement.
I have the following data (there is another column image of type mediumblob which is not shown):
id title test_id
1 bomb 0
2 Soft watch 2
3 Dali 1
4 Narciss 1
5 The Woman In Green 0
6 A summer in Vetheuil 0
7 Artist's Garden 2
8 Beech Forest 2
9 Claude Monet 0
I know if I perform
select max(id) from images
where image is not null;
I get the max value of id i.e.:
max(id)
9
However can someone please explain what is happening when I perform
select max(id), title, test_id
from images
where image is not null
group by id;
I find that the max(id) serves no useful purpose (results shown below)?
max(id) title test_id
1 bomb 0
2 Soft watch 2
3 Dali 1
4 Narciss 1
5 The Woman In Green 0
6 A summer in Vetheuil 0
7 Artist's Garden 2
8 Beech Forest 2
9 Claude Monet 0
In the case of using MAX() the GROUP BY clause essentially tells the query engine how to group the items from which to determine a maximum. In your first example you were selecting only a single column, so there was no need for grouping. But in your second example you had multiple columns. So you need to tell the query engine how to determine which ones are going to be compared to find a maximum.
You told it to group by the id column. Which means that it's going to compare records which have the same id and give you the maximum one for each unique id. Since every record has a different id, you essentially didn't do anything with that clause.
It grouped all records with an id of 1 (which was a single record), and returned the record with the maximum id from that group (which was that record). It did the same for 2, 3, etc.
In the case of the three columns shown here, the only place where it would make sense to group your records would be on the test_id column. Something like this:
SELECT MAX(id), title, test_id
FROM images
WHERE image IS NOT null
GROUP BY test_id
This would group them by the test_id, so the results will include records 6 (the maximum id for test_id 0), 4 (the maximum id for test_id 1), and 8 (the maximum id for test_id 2). By splitting the records into those three groups based on the three unique values in the test_id column, it can effectively find a "maximum" id within each group.
Yes, in your example it serves no useful purpose.
You're grouping by ID then finding the maximum ID. But that doesn't make sense since there's only one of each ID. Normally MAX() is used on quantities, like prices or item counts or such like.
Group by is not used for this kind of queries
Its is used for queries like this
OId OrderDate OrderPrice Customer
1 2008/11/12 1000 Hansen
2 2008/10/23 1600 Nilsen
3 2008/09/02 700 Hansen
4 2008/09/03 300 Hansen
5 2008/08/30 2000 Jensen
6 2008/10/04 100 Nilsen
Now if you want to get sum of material bought by each customer of these you will use group by
SELECT Customer,SUM(OrderPrice) FROM Orders
GROUP BY Customer
customer SUM(OrderPrice)
Hansen 2000
Nilsen 1700
Jensen 2000
In above case id is unique so group by id will not make any sense