MySQL Query - IF or CASE with AND & Exceptions (for calculations) - mysql

SQL Query - extract cell value for calculations as below
Info: Server version: 5.1.39
Php: 5.4
MySQL / phpMyAdmin
Server: Apache
Code is run via: Server SQL Query (copy & paste in the phpMyAdmin) or in MySQL Workbench or using a custom shopping cart manager.
Exports to: Excel (.csv then to .xlsx for sales reports)
Other: I do use a number of tables for referencing
I am trying to write a string (so far WHEN & IF) to do the following:
T5.coupon_code = XYZABC
AND T3.products_id=14 then the value is $5.00
as Ded_Promo
T5.coupon_code = XYZABC
AND (T3.products_id=Anything else) then the value is $0.00
as Ded_Promo
(see table lines 1 & 2 for example).
code tried:
(IF(T5.coupon_code=XYZABC And T3.products_id=14,'5.00','0.00')) As Ded_promo2,
Result: Error Code: 1054. Unknown column 'XYZABC' in 'field list'
The coupon_code value is legit, when I run a query on the coupon_code the code that I am wanting to query shows as being used. (XYZABC is substituted for my real code).
Also tried:
CASE When (T5.coupon_code = XYZABC) then '5.00'
end As Ded_Promo,
Same error as above.
I then need to have the code further expanded to show:
If code & product match = $5.00 As Ded_Promo (as above)
But if code is present (say ID: ABC123DEF), then 'value' (as listed) As Disc_CoupVal
Ideally I need to make sure that the Promo discount doesn't get attributed to other products in the order, whilst the front end calculates it as 1 sale. My reports require that I keep discount coupons and special promotions connected to ONLY the product they are discounting. Commissions rely on this.
However I still need to see all other coupons listed and attribute them across an entire order of 1 or more products.
There will never be more than 1 coupon_code on any given order, the store doesn't allow it.
From above:
orderid | couponcode | ProdID | Discount
21 | XYZABC | 14 | 5.00
21 | XYZABC | 12 | 0.00
36 | ABC123DEF | 3 | 2.50

(IF(T5.coupon_code=XYZABC And T3.products_id=14,'5.00','0.00')) As Ded_promo2
This is causing an error because you are using XYZABC as a column name. Use it as a string:
(IF(T5.coupon_code='XYZABC' And T3.products_id=14,'5.00','0.00')) As Ded_promo2
Edit:
In response to your comments, you can include these in the same column but it's a bit messier:
(IF(
T5.coupon_code='XYZABC' And T3.products_id=14,
'5.00',
(IF(
T5.coupon_code='AnyotherCoupon' And T3.products_id='AnyotherID',
'CouponValue',
'0.00'))
)) As Ded_promo2,
So the above will show 5 if the code is XYZABC and product id is 14.
Otherwise if code is AnyotherCoupon and id is AnyotherID it will show CouponValue.
If neither of these are the case then it will show 0.00.
One thing to note that if there is a lot of these it would be better to store the promotion amount in the database (perhaps as a coupon table?). This keeps the SQL neater and allows you to more easily add and change coupons.

(IF(T5.coupon_code='XYZABC' And T3.products_id=14,'5.00','0.00')) As Ded_promo2,
Try putting single quotes around the XYZABC. This makes the term a literal character string, instead of a named data item in SQL.

Related

MySql: adding columns dynamically, as many as rows in another table

Transport table
id name
1 T1
2 T2
Pallets table
id name
1 P1
2 P2
Transport Pallet Capacity table
id transport_id pallet_id capacity
1 1 1 10
2 1 2 null
3 2 1 20
4 2 2 24
How to generate table like this:
id transport_id pallet_id_1_capacity pallet_id_2_capacity
1 1 10 null
2 2 20 24
Problem: pallets and transports can be added, so, neither quantity is known in advance.
For example, manager adds another pallet type and 'pallet_id_3_capacity' column should be generated (and can show null if no capacity data is yet available).
Another manager can fill 'transport pallet capacity' table later when notified.
Is there a way to build sql in mysql that will care about the above: specifically - dynamic number of pallets?
The SQL select-list must be fixed at the time you write the query. You can't make SQL that auto-expands its columns based on the data it finds.
But your request is common, it's called a pivot-table or a crosstab table.
The only solution is to do this in multiple steps:
Query to discover the distinct pallet ids.
Use application code to build a dynamic SQL query with as many columns as distinct pallet id values found in the first query.
Run the resulting dynamic SQL query.
This is true for all SQL databases, not just MySQL.
See MySQL pivot row into dynamic number of columns for a highly-voted solution for producing a pivot-table query in MySQL.
I am not voting your question as a duplicate of that question, because your query also involves transport_id, which will make the query solution a bit different. But reading about other pivot-table solutions should get you started.

How to balance out row mode and column mode in cygnus?

I have a weather-station that transmits data each hour. During that hour it makes four recordings (one every 15 minutes). In my current situation I am using attr_persistence=row to store data in my MySql database.
With row mode I get the default generated columns:
recvTimeTs | recvTime | entityId | entityType | attrName | attrType | attrValue | attrMd
But my weather station sends me the following data:
| attrName | attrValue
timeRecorded 14:30:0,22.5.2015
measurement1 18.799
measurement2 94.0
measurement3 1.19
These attrValue are represented in the database as string.
Is there a way to leave the three measurements in row mode and switch the timeRecorded to column mode? And if not, then what is my alternative?
The point of all this is to query the time recorded value, but I cannot query date as long as it is string.
As a side note: having the weather station send the data as soon as it is recorded (every 15 minutes) is out of the question, firstly because I need to conserve battery power and more importantly because in the case of a problem with the post, it will send all of the recordings at once.
So if an entire day went without sending any data, the weather station will send all 24*4 readings at once...
The proposed solution is to use the STR_TO_DATE function of MySQL in order to translate the stored string-based "timeRecorded" attribute into a real MySQL Timestamp type.
Nevertheless, "timeRecorded" attribute appears every 4 rows in the table due to the "row" attribute persistence mode of OrionMySQLSink. In this case I think you can use the ROWNUM keyword from MySQL in order to get only every 4 rows, something like (not an expert on MySQL):
SELECT STR_TO_DATE( attrValue, '%m/%d/%Y' ) FROM def_servpath_0004_weatherstation where (ROWNUM / 4 = 0);
The alternative is to move to "column" mode (in this case you have to provision de table by yourself). By using this mode you will have a single row with all the 4 attributes, being one of these attributes the "timeRecorded" one. In this case, you can provision the table by directly specifying the type of the "timeRecorded" column as Timestamp, instead of Text. That way, you will avoid the STR_TO-DATE part.

database schema one column entry references many rows from another table

Let's say we have a table called Workorders and another table called Parts. I would like to have a column in Workorders called parts_required. This column would contain a single item that tells me what parts were required for that workorder. Ideally, this would contain the quantities as well, but a second column could contain the quantity information if needed.
Workorders looks like
WorkorderID date parts_required
1 2/24 ?
2 2/25 ?
3 3/16 ?
4 4/20 ?
5 5/13 ?
6 5/14 ?
7 7/8 ?
Parts looks like
PartID name cost
1 engine 100
2 belt 5
3 big bolt 1
4 little bolt 0.5
5 quart oil 8
6 Band-aid 0.1
Idea 1: create a string like '1-1:2-3:4-5:5-4'. My application would parse this string and show that I need --> 1 engine, 3 belts, 5 little bolts, and 4 quarts of oil.
Pros - simple enough to create and understand.
Cons - will make deep introspection into our data much more difficult. (costs over time, etc)
Idea 2: use a binary number. For example, to reference the above list (engine, belt, little bolts, oil) using an 8-bit integer would be 54, because 54 in binary representation is 110110.
Pros - datatype is optimal concerning size. Also, I am guessing there are tricky math tricks I could use in my queries to search for parts used (don't know what those are, correct me if I'm in the clouds here).
Cons - I do not know how to handle quantity using this method. Also, Even with a 64-bit BIGINT still only gives me 64 parts that can be in my table. I expect many hundreds.
Any ideas? I am using MySQL. I may be able to use PostgreSQL, and I understand that they have more flexible datatypes like JSON and arrays, but I am not familiar with how querying those would perform. Also it would be much easier to stay with MySQL
Why not create a Relationship table?
You can create a table named Workorders_Parts with the following content:
|workorderId, partId|
So when you want to get all parts from a specific workorder you just type:
select p.name
from parts p inner join workorders_parts wp on wp.partId = p.partId
where wp.workorderId = x;
what the query says is:
Give me the name of parts that belongs to workorderId=x and are listed in table workorders_parts
Remembering that INNER JOIN means "INTERSECTION" in other words: data i'm looking for should exist (generally the id) in both tables
IT will give you all part names that are used to build workorder x.
Lets say we have workorderId = 1 with partID = 1,2,3, it will be represented in our relationship table as:
workorderId | partId
1 | 1
1 | 2
1 | 3

Sequence Number in ms access

I want to create sequence number in my order form that after save button it generate a Order No in Order No field of table, as I m not much knowledge in VBA but got from internet some codes which i try to implement but its not working
The code is given below please see reply if there is any edit or where i m mistaked
Table:
ID | date | party Name | Order No| Item | qty | Rate | Amount |
Private Sub save_Click()
If Me.orderno = Null Then
Me.orderno = Nz(DMax([Order No], Order), 0) + 1
End If
End Sub
If the name of the table is 'Order', the following should work:
If IsNull(Me.orderno) Then
Me.orderno = Nz(DMax("[Order No]", "Order"), 0) + 1
End If
A few other comments:
Date is a reserved word and should not be used as a field name, so best to change it to avoid problems. http://office.microsoft.com/en-us/access-help/access-2007-reserved-words-and-symbols-HA010030643.aspx
It is also poor practice to use spaces in field names.
The problems here were quite obvious, however, for future reference, you should state what error you are receiving and which line it occurs on. 'Not working' does not provide any clues.
Add the line
DoCmd.RunCommand acCmdSaveRecord
at the end, to insure that the record is saved.
Make sure that the code is actually running and that orderno is bound to the field orderno.
If it still doesn't appear to work, step through he code to see what is happening.
As for the comment about autonumber, and autonumber is fine if you don't care about gaps in the numbering sequence, which will eventually occur using an autonumber.

MySQL, how to repeat same line x times

I have a query that outputs address order data:
SELECT ordernumber
, article_description
, article_size_description
, concat(NumberPerBox,' pieces') as contents
, NumberOrdered
FROM customerorder
WHERE customerorder.id = 1;
I would like the above line to be outputted NumberOrders (e.g. 50,000) divided by NumberPerBox e.g. 2,000 = 25 times.
Is there a SQL query that can do this, I'm not against using temporary tables to join against if that's what it takes.
I checked out the previous questions, however the nearest one:
is to be posible in mysql repeat the same result
Only gave answers that give a fixed number of rows, and I need it to be dynamic depending on the value of (NumberOrdered div NumberPerBox).
The result I want is:
Boxnr Ordernr as_description contents NumberOrdered
------+--------------+----------------+-----------+---------------
1 | CORDO1245 | Carrying bags | 2,000 pcs | 50,000
2 | CORDO1245 | Carrying bags | 2,000 pcs | 50,000
....
25 | CORDO1245 | Carrying bags | 2,000 pcs | 50,000
First, let me say that I am more familiar with SQL Server so my answer has a bit of a bias.
Second, I did not test my code sample and it should probably be used as a reference point to start from.
It would appear to me that this situation is a prime candidate for a numbers table. Simply put, it is a table (usually called "Numbers") that is nothing more than a single PK column of integers from 1 to n. Once you've used a Numbers table and aware of how it's used, you'll start finding many uses for it - such as querying for time intervals, string splitting, etc.
That said, here is my untested response to your question:
SELECT
IV.number as Boxnr
,ordernumber
,article_description
,article_size_description
,concat(NumberPerBox,' pieces') as contents
,NumberOrdered
FROM
customerorder
INNER JOIN (
SELECT
Numbers.number
,customerorder.ordernumber
,customerorder.NumberPerBox
FROM
Numbers
INNER JOIN customerorder
ON Numbers.number BETWEEN 1 AND customerorder.NumberOrdered / customerorder.NumberPerBox
WHERE
customerorder.id = 1
) AS IV
ON customerorder.ordernumber = IV.ordernumber
As I said, most of my experience is in SQL Server. I reference http://www.sqlservercentral.com/articles/Advanced+Querying/2547/ (registration required). However, there appears to be quite a few resources available when I search for "SQL numbers table".