How do you properly construct an IF EXIST UPDATE ELSE INSERT? - mysql

I have a tables containing the dollars a customer spends as well as points they earn. I have a master table that I intend to accumulate the points/dollars and redistribute them to the stores so that points are shared accross all stores. The query to determine the difference of the master table (CMCustomer) and the store tables (cm01, cm03, etc...) are as follows, a separate query for each store.
use customer;
truncate cm01process;
INSERT INTO cm01process
select cm01.CustomerNumber,
cm01.LastName,
cm01.FirstName,
cm01.Address,
cm01.City,
cm01.State,
cm01.ZIPCode,
cm01.PhoneNo,
cm01.DriverLicenseNo,
cm01.SocialSecNo,
cm01.TaxExempt,
cm01.ExternalRefNumber,
cm01.AuxField,
cm01.Comments,
cm01.FSLevelNo,
cm01.FSDateOpened,
cm01.FSLastVisit,
IFNULL(IF( (cm01.FSVisitsToDate - CMCustomer.FSVisitsToDate) < 0, 0, (cm01.FSVisitsToDate - CMCustomer.FSVisitsToDate) ), 0 ) AS FSVisitsToDate,
IFNULL(IF( (cm01.FSVisitsThisPeriod - CMCustomer.FSVisitsThisPeriod) < 0, 0, (cm01.FSVisitsThisPeriod - CMCustomer.FSVisitsThisPeriod) ), 0 ) AS FSVisitsThisPeriod,
IFNULL(IF( (cm01.FSPurchaseToDate - CMCustomer.FSPurchaseToDate) < 0, 0, (cm01.FSPurchaseToDate - CMCustomer.FSPurchaseToDate) ), 0 ) AS FSPurchaseToDate,
IFNULL(IF( (cm01.FSPurchaseThisPeriod - CMCustomer.FSPurchaseThisPeriod) < 0, 0, (cm01.FSPurchaseThisPeriod - CMCustomer.FSPurchaseThisPeriod) ), 0 ) AS FSPurchaseThisPeriod,
IFNULL(IF( (cm01.FSDiscountToDate - CMCustomer.FSDiscountToDate) < 0, 0, (cm01.FSDiscountToDate - CMCustomer.FSDiscountToDate) ), 0 ) AS FSDiscountToDate,
IFNULL(IF( (cm01.FSDiscountThisPeriod - CMCustomer.FSDiscountThisPeriod) < 0, 0, (cm01.FSDiscountThisPeriod - CMCustomer.FSDiscountThisPeriod) ), 0 ) AS FSDiscountThisPeriod,
IFNULL(IF( (cm01.FSPointsToDate - CMCustomer.FSPointsToDate) < 0, 0, (cm01.FSPointsToDate - CMCustomer.FSPointsToDate) ), 0 ) AS FSPointsToDate,
IFNULL(IF( (cm01.FSPointsThisPeriod - CMCustomer.FSPointsThisPeriod) < 0, 0, (cm01.FSPointsThisPeriod - CMCustomer.FSPointsThisPeriod) ), 0 ) AS FSPointsThisPeriod,
IFNULL(IF( (cm01.FSPromoPointsToDate - CMCustomer.FSPromoPointsToDate) < 0, 0, (cm01.FSPromoPointsToDate - CMCustomer.FSPromoPointsToDate) ), 0 ) AS FSPromoPointsToDate,
IFNULL(IF( (cm01.FSPromoPointsThisPeriod - CMCustomer.FSPromoPointsThisPeriod) < 0, 0, (cm01.FSPromoPointsThisPeriod - CMCustomer.FSPromoPointsThisPeriod) ), 0 ) AS FSPromoPointsThisPeriod,
cm01.LastUpdated
from cm01
left join CMCustomer on cm01.CustomerNumber = CMCustomer.CustomerNumber;
This query works fine. The next query is where I begin to have problems.
-EDIT-
I have updated the second query. It is not producing errors and appears to do mostly what I want however it is not adding properly. In the query below it should insert into the new table (processData) the fields from a selection. On duplicates it is supposed to update the fields specified and on new rows just add them. It appears to work ok except when the UPDATE is performed it returns all zeroes in those columns. Example: CMCustomer has 55 points, cm01process had 0 points. Instead of adding the two points together and giving me 55 it is returning 0. Any ideas what I have wrong here?
use customer;
INSERT INTO processData (CustomerNumber,
LastName,
FirstName,
Address,
City,
State,
ZIPCode,
PhoneNo,
DriverLicenseNo,
SocialSecNo,
TaxExempt,
ExternalRefNumber,
AuxField,
Comments,
FSLevelNo,
FSDateOpened,
FSLastVisit,
FSVisitsToDate,
FSVisitsThisPeriod,
FSPurchaseToDate,
FSPurchaseThisPeriod,
FSDiscountToDate,
FSDiscountThisPeriod,
FSPointsToDate,
FSPointsThisPeriod,
FSPromoPointsToDate,
FSPromoPointsThisPeriod,
LastUpdated)
SELECT cm01process.CustomerNumber,
cm01process.LastName,
cm01process.FirstName,
cm01process.Address,
cm01process.City,
cm01process.State,
cm01process.ZIPCode,
cm01process.PhoneNo,
cm01process.DriverLicenseNo,
cm01process.SocialSecNo,
cm01process.TaxExempt,
cm01process.ExternalRefNumber,
cm01process.AuxField,
cm01process.Comments,
cm01process.FSLevelNo,
cm01process.FSDateOpened,
cm01process.FSLastVisit,
cm01process.FSVisitsToDate,
cm01process.FSVisitsThisPeriod,
cm01process.FSPurchaseToDate,
cm01process.FSPurchaseThisPeriod,
cm01process.FSDiscountToDate,
cm01process.FSDiscountThisPeriod,
cm01process.FSPointsToDate,
cm01process.FSPointsThisPeriod,
cm01process.FSPromoPointsToDate,
cm01process.FSPromoPointsThisPeriod,
cm01process.LastUpdated
FROM cm01process
LEFT JOIN CMCustomer ON cm01process.CustomerNumber = CMCustomer.CustomerNumber
ON DUPLICATE KEY UPDATE
processData.FSVisitsToDate = CMCustomer.FSVisitsToDate + cm01process.FSVisitsToDate,
processData.FSVisitsThisPeriod = CMCustomer.FSVisitsThisPeriod + cm01process.FSVisitsThisPeriod,
processData.FSPurchaseToDate = CMCustomer.FSPurchaseToDate + cm01process.FSPurchaseToDate,
processData.FSPurchaseThisPeriod = CMCustomer.FSPurchaseThisPeriod + cm01process.FSPurchaseThisPeriod,
processData.FSDiscountToDate = CMCustomer.FSDiscountToDate + cm01process.FSDiscountToDate,
processData.FSDiscountThisPeriod = CMCustomer.FSDiscountThisPeriod + cm01process.FSDiscountThisPeriod,
processData.FSPointsToDate = CMCustomer.FSPointsToDate + cm01process.FSPointsToDate,
processData.FSPointsThisPeriod = CMCustomer.FSPointsThisPeriod + cm01process.FSPointsThisPeriod,
processData.FSPromoPointsToDate = CMCustomer.FSPromoPointsToDate + cm01process.FSPromoPointsToDate,
processData.FSPromoPointsThisPeriod = CMCustomer.FSPromoPointsThisPeriod + cm01process.FSPromoPointsThisPeriod

Related

MySQL Tagging Rows in Sequence based on a pattern

I have a column which I am trying to convert in MySQL into another column with a pattern where ever there are consecutive 1s in the data. Please see the example dataset below
Dataset Sample: https://1drv.ms/x/s!ApGNZAoiMmX3gi9OR7SUxt3ou84v?e=tuSV7f
Following is the code I have written but not able to make it work and any suggestions would be helpful.
select rownum,result,movingsum,new_result
(select rownum,result,movingsum,
if(result_norm_max=0,0,if(movingsum=1,1,0)) as new_result
from
(select rownum,result,
sum(result) over (order by rownum rows between 2 preceding and current row) as movingsum
from mytable) a;
The issue is, the above code doesn't return the output needed for all required logic of:
when result column is 0 new_result should be 0
when result is 1, new_result = 1 but only when previous 2 new_results are 0
Any suggestion on how I should approach this will be useful.
Thanks!
With some tries I was able to find the solution which is close to what I need as mentioned below. I used 2 variables to carry out the trick,
select rownum,result,
if (result= 0, 0, if(#n = 1, if(#m >= 7, 1 , 0), 1)) as new_max,
if (result= 0, 0, if(#n = 1,
case when #m >= 7 then #m:=0 else 0 end
, 1)) as new_max1,
if (result= 0, if(#m>0,#m:=#m-1,#m:=0), if(#n = 1, #m:=#m+1,#m:=#m-1)) as new_m,
#n := result
from mytable a, (select #n:= 0, #m:= 0) b

Mysql order by sorting not working as expected descending

i am facing a a very strange behavior regarding mysql orderby sort, I am trying to sort the records by fee_range high to low which is being computed in run time first 3,4 rows have lowest values and then order by takes effect and and further all records are sorted as expected is there any thing that i am missing?
here is the query that i am running
SELECT `ddd`.`ID`, CONCAT(ddd.title, " ", ddd.name) AS name, `ddd`.`url`, `ddd`.`doc_gender`, `ddd`.`edu_degrees`, TRIM(BOTH ", " FROM ddd.specializations) AS specializations, `ddd`.`tel_appointments`, CONCAT("https://s3-eu-west-1.amazonaws.com/mdpk/images/profile-pics/doctors/", ddd.profile_image) AS profile_image, `ddd`.`yearsofexperience`, IF(MIN(IF(daas.fee > 0, `daas`.`fee`, NULL)) = MAX(IF(daas.fee > 0, `daas`.`fee`, NULL)), MIN(IF(daas.fee > 0, `daas`.`fee`, NULL)), CONCAT(MIN(IF(daas.fee > 0, `daas`.`fee`, NULL)), "-", MAX(IF(daas.fee > 0, `daas`.`fee`, NULL)))) AS fee_range, `dhdtl`.`locality`, `dhdtl`.`city`, `ddd`.`star_rating`, `ddd`.`is_paying`, `ddd`.`divert_to_cc`, `ddd`.`patient_records`, IF(MAX(daas.allow_online_booking + daas.has_active_subs) = 2, 1, 0) AS is_bookable, MAX(daas.has_active_subs) AS has_active_subscription, `ddd`.`verified_patients`, `ddd`.`average_wait_time`, (ddd.positive_reviews + ddd.negative_reviews) AS total_reviews, IF(ddd.verified_patients > 0 AND
ddd.positive_reviews + ddd.negative_reviews > 0 AND
ddd.positive_reviews + ddd.negative_reviews > 0 AND
(ddd.is_paying = 1 OR 1 = 0), ROUND(ddd.positive_reviews * 100 / (ddd.positive_reviews + ddd.negative_reviews), 0), 0) AS recommendation_percentage
FROM `doc_doc_details` AS `ddd`
JOIN `doc_specialization_relation` `dsr` ON `dsr`.`user_id` = `ddd`.`ID`
JOIN `doc_hosp_doctor` `dhd` ON `ddd`.`ID` = `dhd`.`user_id`
JOIN `doc_app_adv_settings` `daas` ON `dhd`.`hospital_id` = `daas`.`subs_id` AND `daas`.`prov_id`=`ddd`.`ID`
JOIN `doc_hospital_details` `dhdtl` ON `dhd`.`hospital_id` = `dhdtl`.`hosp_detail_id`
WHERE `dhdtl`.`country_id` = 1
AND `dhdtl`.`city_id` = '1'
AND `dsr`.`specialization_id` IN('72')
AND `ddd`.`published` = 1
GROUP BY `ddd`.`ID`
ORDER BY `has_active_subscription` DESC, MAX(fee_range) DESC, `ddd`.`manual_web_rank`, `ddd`.`computed_web_rank`, `dhd`.`is_primary` DESC
LIMIT 20
here are the results
any help regarding this issue would be really appreciated
The CONCAT-function inside the fee_range-column turns the column into a character column (causing ordering by alphabetical order) and you are ordering the column with MAX(fee_range) whereas it should be just fee_range.

How to format to display leading zero

I am trying to display the duration in this format: 05:02:09 which is hour, minute and second.
At the moment I can display it without the leading zero in this format: 5:02:09
=IIF(
Fields!DataValue.Value < 0, 0,
Floor(Fields!DataValue.Value / 3600) &":"&Format(
DateAdd("s",IIF(Fields!DataValue.Value < 0, 0, Fields!DataValue.Value),"00:00"),
"mm:ss"
)
)
How can add a leading zero when the hour is less than 10?
I found a solution, which I tried before but failed. Strangely, it worked this time.
=IIF(
Fields!DataValue.Value < 0, 0,
Format(Floor(Fields!DataValue.Value / 3600), "00") &":"&Format(
DateAdd("s",IIF(Fields!DataValue.Value < 0, 0, Fields!DataValue.Value),"00:00"),
"mm:ss"
)
)

Adding an iif statement or where clause

Here is my current expression
=IIf(Fields!Units_Sold.Value = 0, 0, Fields!Total_Incidents.Value / IIf(Fields!Units_Sold.Value = 0, 1, Fields!Units_Sold.Value))
I need to add where Fields!.TECHNOLOGY = "Wired" to the above statement I tried a couple different things but with no success.
Try this:
=IIf(Sum(iif(Fields!technology.Value = "wired",Fields!Units_Sold.Value,0)) = 0,
0,
sum(iif(Fields!technology.Value="wired",Fields!Total_Incidents.Value,0)) /
IIf(Sum(iif(Fields!technology.Value = "wired",
Fields!Units_Sold.Value,0)) = 0, 1,
Sum(iif(Fields!technology.Value = "wired",Fields!Units_Sold.Value,0))
)
)
It is not tested but should work. Let me know if this could help you

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

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.