How can I use Math Formula in a MySQL query? - mysql

I am creating a CPM and I am trying to get all the CPM that are not on track. I have the follow code below and I have put the formula in the WHERE clause, but it shows all results. Instead of only results that are less than 0.9.
SELECT cpms.*, site_images.*
FROM ( cpm_images
INNER JOIN site_images ON ( cpm_images.site_image_id = site_images.site_image_id ) )
INNER JOIN cpms
ON
( cpms.cpm_id = cpm_images.cpm_id )
WHERE (
( cpms.cpm_views_count * ( $data - cpms.cpm_date_start ) ) /
( cpms.cpm_views_total * (cpms.cpm_date_end - $data ) )
) < 0.9
No matter what number is calculated it show the all the results. If the number is below 0.9 it shows, if it is above 0.9, it shows.
UPDATE:
the following data is what is being pulled from the datbase.
This is the data from the table.
[cpm_id] => 1
[cpm_title] => Ad Special
[cpm_date_start] => 1556746806
[cpm_date_end] => 1559425206
[cpm_views_total] => 1000
[cpm_views_count] => 500
[cpm_image] =>
[cpm_active] => 1
[site_image_id] => 137
[site_image_file] => cars/3.jpg
[site_image_file_tn] => cars/3.jpg
[site_image_file_org] => cars/3.jpg
[site_image_title] =>
[site_image_description] =>
[site_image_upload_date] => 0
When i places numbers in place of the table row names
( 500 * ( 1557665447 - 1559425206 ) )
/
( 1000 * ( 1556746806 - 1557665447 ) )
it works, so is it possible that the table row names are not showing as int. yet the table is as follows
`cpm_id` int(11) UNSIGNED NOT NULL,
`cpm_title` varchar(255) NOT NULL,
`cpm_date_start` int(11) NOT NULL,
`cpm_date_end` int(11) NOT NULL,
`cpm_views_total` int(11) NOT NULL,
`cpm_views_count` int(11) NOT NULL,
`cpm_image` varchar(255) DEFAULT NULL,
`cpm_active` int(1) DEFAULT NULL
if I have the numbers
( 0 * ( 1557665447 - 1559425206 ) ) / ( 1000 * ( 1556746806 - 1557665447 ) )
it equals to 0 so it shows as it is below 0.9
BUT if i have the follow
( 1000 * ( 1557665447 - 1559425206 ) ) / ( 1000 * ( 1556746806 - 1557665447 ) )
which equals to 1.91561121265 which it shows in the results, but it shouldn't as it is not smaller then 0.9
UPDATE:
if i use the follow
WHERE ( ( cpms.cpm_views_count * ( 1557665447 - 1559425206 ) ) / ( cpms.cpm_views_total * ( 1556746806 - 1557665447 ) ) ) < 0.9
It works, and the following works too
WHERE ( ( cpms.cpm_views_count * ( $date - 1559425206 ) ) / ( cpms.cpm_views_total * ( 1556746806 - $date ) ) ) < 0.9
but as soon as i change it to
WHERE ( ( cpms.cpm_views_count * ( $date - cpms.cpm_date_start ) ) / ( cpms.cpm_views_total * ( cpms.cpm_date_end - $date ) ) ) < 0.9
it does not work, I even try putting brackets around cpms.cpm_date_end and cpms.cpm_date_start and it still failed.

I have found the issue, I had the cpm_views_start and cpm_views_end wrong way around
( ( cpms.cpm_views_count * ( $date - cpms.cpm_date_end ) ) / ( cpms.cpm_views_total * ( cpms.cpm_date_start - $date) ) )
How I realized this was when I put it in as follows
SELECT ( ( cpms.cpm_views_count * ( $date - cpms.cpm_date_end ) ) / ( cpms.cpm_views_total * ( cpms.cpm_date_start - $date) ) ) AS sum_2
it came back a different number. I realize somewhere during coding the string I change the cpm_date_end and cpm_date_start around, yet in where i had it showing on the screen for testing, it was the correct way, so the data on the screen was correct but when it was calculating it in the query, it was wrong way about.
Thank you #nick for doing what you can to help me.

Related

Converting a DAX expression to an SSRS expression

I have these two expressions to convert from DAX expressions to SSRS expressions, I am trying to replicate this expression in an ssrs environment to determine the metrics as shown below. I quite understand the expression but finding the appropriate expression to articulate this expression in ssrs seems to be the issue
ABS (
CALCULATE ( [CashAmount], PATHCONTAINS ( 'Account'[Account Hierarchy], "ABC" ) )
) < 1,
BLANK (),
DIVIDE (
CALCULATE ( [CashAmount], PATHCONTAINS ( 'Account'[Account Hierarchy], "ABC" ) ),
CALCULATE ( [CashAmount], PATHCONTAINS ( 'Account'[Account Hierarchy], "XYZ" ) )
)
) * -1 ```
and ```CALCULATE (
[CashAmount],
FILTER (
ALL ( 'Account' ),
PATHCONTAINS ( 'Account'[Account Hierarchy], "ABC" )
)
)
+ CALCULATE (
[CashAmount],
FILTER (
ALL ( 'Account' ),
PATHCONTAINS ( 'Account'[Account Hierarchy], "EFG" )
)
)
+ CALCULATE (
[CashAmount],
FILTER (
ALL ( 'Account' ),
PATHCONTAINS ( 'Account'[Account Hierarchy], "HIJK" )
)
)
+ CALCULATE (
[CashAmount],
FILTER (
ALL ( 'Account' ),
PATHCONTAINS ( 'Account'[Account Hierarchy], "LMNO" )
)
) ```

Multiply kg and grams unit with price per kg

I'm currently have a task when I have to calculate the values for the cost of supplies which I have to multiply priceperweight with weight. But in weight there's also kg and grams. When I multiply it, it gives the results like $3000 for 500 grams of Spinach. Here's my scheme. Please help. All help would be appreciated :D Here's my code! Thank you so much
select PricePerWeight * Weight from Supplies;
Normalize the weight to grams or Kg (I'll use grams) using CASE x WHEN y:
SELECT
s.*,
CASE s.metric
WHEN 'Kilos' THEN ( s.weight * 1000 )
WHEN 'grams' THEN ( s.weight * 1 ) ELSE NULL
END AS weightInGrams
FROM
supplies AS s
Then adding additional units is straightforward:
SELECT
s.*,
CASE s.metric
WHEN 'tonnes' THEN ( s.weight * 1000 * 1000 )
WHEN 'Kilos' THEN ( s.weight * 1000 )
WHEN 'grams' THEN ( s.weight * 1 )
WHEN 'jupiter' THEN ( s.weight * 1.9 * POW( 10, 27 ) * 1000 )
WHEN 'lbs' THEN ( s.weight * 453.592 ) ELSE NULL
END AS weightInGrams
FROM
supplies AS s
Assuming you're using ISO-compliant SQL, you'll need to use an outer-query or a CTE to then multiply by pricePerWeight, which I assume is in Kg:
Note that the queries below still use grams as the base unit of mass to avoid problems caused by integer division (as SQL does not make it easy to make sure numeric literals are processed as floats or decimals instead of integers, as integer division truncates rather than rounds).
The final value is the thePrice column in the queries below:
Option 1: Using an outer-query:
SELECT
s2.*,
( s2.pricePerWeight * s2.weightInGrams ) / 1000.00 AS thePrice
FROM
(
SELECT
s.*,
CASE s.metric
WHEN 'tonnes' THEN ( s.weight * 1000 * 1000 )
WHEN 'Kilos' THEN ( s.weight * 1000 )
WHEN 'grams' THEN ( s.weight * 1 )
WHEN 'jupiter' THEN ( s.weight * 1.9 * POW( 10, 27 ) * 1000 )
WHEN 'lbs' THEN ( s.weight * 453.592 ) ELSE NULL
END AS weightInGrams
FROM
supplies AS s
)
Option 2: Using a CTE:
WITH s2 AS (
SELECT
s.*,
CASE s.metric
WHEN 'tonnes' THEN ( s.weight * 1000 * 1000 )
WHEN 'Kilos' THEN ( s.weight * 1000 )
WHEN 'grams' THEN ( s.weight * 1 )
WHEN 'jupiter' THEN ( s.weight * 1.9 * POW( 10, 27 ) * 1000 )
WHEN 'lbs' THEN ( s.weight * 453.592 ) ELSE NULL
END AS weightInGrams
FROM
supplies AS s
)
SELECT
s2.*,
( s2.pricePerWeight * s2.weightInGrams ) / 1000.00 AS thePrice
FROM
s2

Inputting data from dataset to SSRS table

I am new to this and i am wondering how to input data into SSRS table and auto generate for the subsequent months. This is the format of the table.
Appreciated for any help given.
You can generate a date range using the following SQL
DECLARE #date_start AS DATETIME
SET #date_start = '01-DEC-2017'
;WITH
finalvalues
AS
(
SELECT tbl.* FROM (VALUES
( '01-Dec-2017', 6414.6563, 429.6846, -1390.8474)
, ( '02-Dec-2017', 6476.6563, 432.751, -1312.4928)
, ( '03-Dec-2017', 6538.6563, 435.8174, -1234.1382)
, ( '04-Dec-2017', 6600.6563, 438.8838, -1155.7836)
, ( '05-Dec-2017', 6662.6563, 441.9502, -1077.429)
, ( '06-Dec-2017', 6724.6563, 445.0166, -999.074399999999)
, ( '07-Dec-2017', 6786.6563, 448.083, -920.719799999999)
, ( '08-Dec-2017', 6848.6563, 451.1494, -842.365199999999)
, ( '09-Dec-2017', 6910.6563, 454.2158, -764.010599999999)
, ( '10-Dec-2017', 6972.6563, 457.2822, -685.655999999999)
, ( '11-Dec-2017', 7034.6563, 460.3486, -607.301399999999)
, ( '12-Dec-2017', 7096.6563, 463.415, -528.946799999999)
, ( '13-Dec-2017', 7158.6563, 466.4814, -450.592199999999)
, ( '14-Dec-2017', 7220.6563, 469.5478, -372.2376)
, ( '15-Dec-2017', 7282.6563, 472.6142, -293.883)
, ( '16-Dec-2017', 7344.6563, 475.6806, -215.5284)
) tbl ([Date], [IncLoad], [ITLoad], [RH])
)
,
manufactured_dates
AS
(
SELECT
day_date = DATEADD(day, dte.[number], #date_start)
FROM
master.dbo.spt_values AS dte
WHERE
1=1 -- <-- used in testing to be able to comment out other clauses below
AND dte.[type] = 'P'
AND dte.[number] <= 365 -- <-- filter how many rows you want to see here
)
SELECT
'Date' = md.[day_date]
, 'IncLoad' = AVG(incload)
, 'ITLoad' = AVG(ITLoad)
FROM
finalvalues AS fv
FULL OUTER JOIN manufactured_dates AS md ON md.[day_date] = fv.[Date]
GROUP BY
md.[day_date]

Relevancy MySQL query to replace stored procedure

I've taken over a project built by my predecessor. That project contains a stored procedure originally taken from here:
https://stackoverflow.com/a/9100182/439925
Currently this is preventing us from updating MySQL, so i have been attempting to remove it and replace the calls to subStringCount() with an adjustment to the top answer on that question.
(( Round (( Char_length(`title`) - Char_length(REPLACE(`title`, 'info', "")) ) / Char_length('info')) * 30 )) AS `title_score`,
The queries are used to count the number of times a search string occurs in a number of fields and then order by the total. Unfortunately i can't get the new query results to match the old one.
The 2 full queries are as follows:
Old WITH the stored Proc:
SELECT SQL_CALC_FOUND_ROWS `temp`.*,
( `title_score` + `source_score`
+ `abstract_score` + `authors_score`
+ `drugs_score` + `uploader_score`
+ `area_score`
+ Ifnull(`document_content_score`, 0) ) AS
`relevance`
FROM (SELECT `kb_uploads`.*,
(( Substringcount(`title`, 'info') * 30 )) AS `title_score`,
(( Substringcount(`source`, 'info') * 15 )) AS`source_score`,
(( Substringcount(`abstract`, 'info') * 20 ) AS`abstract_score`,
(( Substringcount(`authors`, 'info') * 30 )) AS `authors_score`,
(( Substringcount(`drugs`, 'info') * 20 )) AS `drugs_score`,
(( Substringcount(`kb_users`.`name`, 'info') * 20 )) AS `uploader_score`,
(( Substringcount(`kb_upload_areas`.`name`, 'info') * 20 )) AS `area_score`,
( `content_tbl`.`index_score` * 1 ) AS `document_content_score`
FROM `kb_uploads`
LEFT JOIN `kb_users`
ON `kb_users`.`id` = `kb_uploads`.`uploader`
LEFT JOIN `kb_upload_areas`
ON `kb_upload_areas`.`id` = `kb_uploads`.`area`
LEFT JOIN (SELECT `upload`,
Sum(`weighting`) AS `index_score`
FROM `kb_search_index`
WHERE `word` = 'info'
GROUP BY `upload`) AS `content_tbl`
ON `content_tbl`.`upload` = `kb_uploads`.`id`) AS `temp`
WHERE `is_deleted` = 0
HAVING `relevance` > 0
ORDER BY `relevance` DESC
LIMIT 10 OFFSET 0
New WITHOUT the stored Proc:
SELECT SQL_CALC_FOUND_ROWS `temp`.*,
( `title_score` + `source_score`
+ `abstract_score` + `authors_score`
+ `drugs_score` + `uploader_score`
+ `area_score`
+ Ifnull(`document_content_score`, 0) ) AS
`relevance`
FROM (SELECT `kb_uploads`.*,
(( Round (( Char_length(`title`) - Char_length(REPLACE(`title`, 'info', "")) ) / Char_length('info')) * 30 )) AS `title_score`,
(( Round (( Char_length(`source`) - Char_length(REPLACE(`source`,'info' , "")) ) / Char_length('info')) * 15 )) AS `source_score`,
(( Round (( Char_length(`abstract`) - Char_length(REPLACE(`abstract`, 'info', "" ) ) ) / Char_length('info')) * 20 )) AS `abstract_score`,
(( Round (( Char_length(`authors`) - Char_length(REPLACE(`authors`,'info', "")))/Char_length('info')) * 30 )) AS `authors_score`,
(( Round (( Char_length(`drugs`) - Char_length(REPLACE(`drugs`,'info',"")) ) / Char_length('info')) * 20 )) AS `drugs_score`,
(( Round (( Char_length(`kb_users`.`name`) - Char_length(REPLACE(`kb_users`.`name`,'info',""))) / Char_length('info')) * 20 )) AS `uploader_score`,
(( Round (( Char_length(`kb_upload_areas`.`name`) - Char_length(REPLACE(`kb_upload_areas`.`name`,'info', "")) ) / Char_length('info'))* 20 )) AS`area_score`,
( `content_tbl`.`index_score` * 1 ) AS `document_content_score`
FROM `kb_uploads`
LEFT JOIN `kb_users`
ON `kb_users`.`id` = `kb_uploads`.`uploader`
LEFT JOIN `kb_upload_areas`
ON `kb_upload_areas`.`id` = `kb_uploads`.`area`
LEFT JOIN (SELECT `upload`,
Sum(`weighting`) AS `index_score`
FROM `kb_search_index`
WHERE `word` = 'info'
GROUP BY `upload`) AS `content_tbl`
ON `content_tbl`.`upload` = `kb_uploads`.`id`) AS `temp`
WHERE `is_deleted` = 0
HAVING `relevance` > 0
ORDER BY `relevance` DESC
LIMIT 10 OFFSET 0
There are 2 main issues.
1) Ifnull is not working in the NEW query. The table column contains mostly null instead of 0
2) The relevancy numbers in the new query don't match the numbers in the old one, possibly something to do with IFNULL not working.
The full queries are constructed in PHP, i have left the code out as the logic hasnt changed, only the string concats to replace the Stored Proc.

Slow location based search result query

I have a query that I use to find results that are ordered by location. Results also have to account for VAT so this is also in the query. The query can unfortunately take 4+ seconds to run when not cached. Can anyone spot any glaringly obvious issues or suggest anything I can do to improve it?
Just to clarify what is happening in the query:
The distance is calculation is euclidean distance using lat/long
The incvat fields are used to show the price when vat is included
The WHEN / THEN statement is used to put prices of 0 at the very bottom
The query:
SELECT * , ROUND( SQRT( POW( ( 69.1 * ( company_branch_lat - 52.4862 ) ) , 2 ) + POW( ( 53 * ( company_branch_lng - - 1.8905 ) ) , 2 ) ) , 1 ) AS distance,
hire_car_day + ( hire_car_day * 0.2 * ! hire_car_incvat ) AS hire_car_day_incvat,
hire_car_addday + ( hire_car_addday * 0.2 * ! hire_car_incvat ) AS hire_car_addday_incvat,
hire_car_week + ( hire_car_week * 0.2 * ! hire_car_incvat ) AS hire_car_week_incvat,
hire_car_weekend + ( hire_car_weekend * 0.2 * ! hire_car_incvat ) AS hire_car_weekend_incvat
FROM hire_car
LEFT JOIN company_branch ON company_branch_id = hire_car_branchid
LEFT JOIN hire_cartypelink ON hire_cartypelink_carhireid = hire_car_id
LEFT JOIN users ON company_branch_userid = user_id
WHERE 1
GROUP BY hire_car_id
HAVING distance <=30
ORDER BY CASE hire_car_day_incvat
WHEN 0
THEN 40000
ELSE hire_car_day_incvat
END , distance ASC
LIMIT 0 , 30
You can use the mysql spatial extension and save the latitude and longitude as a point datatype and make it a spatial index. That way you can reorder the coordinates along a curve and reduce the dimension and preserve spatial information. You can use the spatial index as a bounding box to filter the query and then use the harvesine formula to pick the optimal result. Your bounding box should be bigger then the radius of the great circle. Mysql uses a rtree with some spatial index and my example was about a z curve or a hilbert curve: https://softwareengineering.stackexchange.com/questions/113256/what-is-the-difference-between-btree-and-rtree-indexing.
Then you can insert a geocoordinate directly into a point column: http://dev.mysql.com/doc/refman/5.0/en/creating-spatial-values.html. Or you can use a geometry datatype: http://markmaunder.com/2009/10/10/mysql-gis-extensions-quick-start/. Then you can use MBRcontains function like so: http://dev.mysql.com/doc/refman/4.1/en/relations-on-geometry-mbr.html or any other functions: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html. Hence you need a bounding box.
Here are some examples:
Storing Lat Lng values in MySQL using Spatial Point Type
https://gis.stackexchange.com/questions/28333/how-to-speed-up-this-simple-mysql-points-in-the-box-query
Here is a simple example with point datatype:
CREATE SPATIAL INDEX sx_place_location ON place (location)
SELECT * FROM mytable
WHERE MBRContains
(
LineString
(
Point($x - $radius, $y - $radius),
Point($x + $radius, $y + $radius)
)
location
)
AND Distance(Point($x, $y), location) <= $radius
MySQL latitude and Longitude table setup.
I'm not sure if it works because it's uses a radius variable with a bounding-box function. It's seems to me MBRwithin is a bit simpler, because it doesn't need any argument: Mysql: Optimizing finding super node in nested set tree.
You are using GROUP BY statement together with HAVING, although I don't see anywhere in the query any aggregate functions. I recommend you to re-write the query like this and see if it makes any difference
SELECT * , ROUND( SQRT( POW( ( 69.1 * ( company_branch_lat - 52.4862 ) ) , 2 ) + POW( ( 53 * ( company_branch_lng - - 1.8905 ) ) , 2 ) ) , 1 ) AS distance,
hire_car_day + ( hire_car_day * 0.2 * ! hire_car_incvat ) AS hire_car_day_incvat,
hire_car_addday + ( hire_car_addday * 0.2 * ! hire_car_incvat ) AS hire_car_addday_incvat,
hire_car_week + ( hire_car_week * 0.2 * ! hire_car_incvat ) AS hire_car_week_incvat,
hire_car_weekend + ( hire_car_weekend * 0.2 * ! hire_car_incvat ) AS hire_car_weekend_incvat
FROM hire_car
LEFT JOIN company_branch ON company_branch_id = hire_car_branchid
LEFT JOIN hire_cartypelink ON hire_cartypelink_carhireid = hire_car_id
LEFT JOIN users ON company_branch_userid = user_id
WHERE ROUND( SQRT( POW( ( 69.1 * ( company_branch_lat - 52.4862 ) ) , 2 ) + POW( ( 53 * ( company_branch_lng - - 1.8905 ) ) , 2 ) ) , 1 ) <= 30
ORDER BY CASE hire_car_day_incvat
WHEN 0
THEN 40000
ELSE hire_car_day_incvat
END , distance ASC
LIMIT 0 , 30