mysql: result counting data as encryption - mysql

i have a problem during count data use this query:
SELECT A.*,
COUNT( B.Serial_number ) AS Qty_insp,
CONCAT(ROUND(A.`Reject_qty`/ COUNT(B.Serial_number)*100, 2),'%') AS NG_Ratio
FROM oqc_defect A
LEFT JOIN inspection_report B ON A.Model = B.Model
AND A.Line = B.Line
GROUP BY A.Problem_date
i get result as encryption code for NG_Ratio like : 3532e......
why its happen, how to resolve this problem?
Edit
Reject_qty Qty_insp NG_Ratio
2 20 10%

Why it's happening: probably it's outputting exponential formatted numbers, like 3532e-2 being equivalent to 35.32.
It's a little hard to tell since you cut off the output at the e, just as it was getting interesting :-)
I think cast() with decimal format may be able to turn that into the desired format or, alternatively, try:
ROUND (A.`Reject_qty` * 100) / COUNT (B.Serial_number), 2)
(I haven't tested this, it may not work).

CONCAT(CAST(ROUND(A.`Reject_qty`/ COUNT(B.Serial_number)*100, 2) AS CHAR),'%') AS NG_Ratio

Related

MYSQL Rounding issue

WHY IS THIS HAPPENING?
SELECT
c.tax_rate,
c.line_item_total_price,
c.shipping_total_price,
ROUND((c.tax_rate *
(c.line_item_total_price+c.shipping_total_price)),2),
(c.tax_rate * (c.line_item_total_price+c.shipping_total_price))
FROM carts c
WHERE c.id = 323002;
returns:
.07
925.00
62.50
69.12
69.125
But this:
SELECT
ROUND((.07 * (925.00+62.50)),2),
(.07 * (925.00+62.50));
Returns the correct:
69.13
69.1250
Why the extra 0 at the end of that one?
FYI: Shipping and line item are DECIMAL(10,2) and tax is DOUBLE
I don't know a lot about MySQL but I would guess that it's an implicit conversion thing based on the column types. Maybe try casting everything until you find out what one was giving you the problem. DECIMAL(10,2) only allows 2 decimal places (that's what the 2 is)
Try
SELECT 1.00 * 1.0
You will get 1.000. This is because the exact result for DECIMAL(a,b) * DECIMAL(c,d) needs a DECIMAL(a+c,b+d) as data type.

SQL - query optimization to work with big data

I have table 33_PROBLEM with columns ROOT and ROOT_CUBED. Ten i have a simple procedure, that insert data, let´s begins with ROOT from -10000 to 10000, which means ROOT_CUBED from -10000^3 to 10000^3.
Question is simple:
How can I get all triplets combinations of ROOT_CUBED values, that add to number given?
Said in different way:
I want to find A, B, C for which is true, that A^3 + B^3 + C^3 = number_given
Here is some example for searched number 33:
SELECT T1.r1,
T2.r2,
T3.r3
FROM (SELECT root_3 AS R1
FROM `33_problem`) AS T1,
(SELECT root_3 AS R2
FROM `33_problem`) AS T2,
(SELECT root_3 AS R3
FROM `33_problem`) AS T3
WHERE T1.r1 + T2.r2 + T3.r3 = 33
It works well ... on a small amount of rows. This query makes (COUNT *)^3 rows, which for 20000 input lines equals to 8e+12 rows !! ... RIP serever ...
what is the right way to solve this one?
( I got the idea from https://www.youtube.com/watch?v=wymmCdLdPvM and I hope, when someone comes with some answers, i will understand better, how SQL works and how queries and databases should be designed to work good even for big data )
1) you could try to only select sequential triplets, such that R1 <= R2 <= R3,
2) if you have duplicates, select distinct
SELECT T1.R1
,T2.R2
,T3.R3
FROM (
SELECT DISTINCT ROOT_3 AS R1
FROM `33_PROBLEM`
) AS T1
,(
SELECT DISTINCT ROOT_3 AS R2
FROM `33_PROBLEM`
WHERE R2>=R1
) AS T2
,(
SELECT DISTINCT ROOT_3 AS R3
FROM `33_PROBLEM`
WHERE R3>=R2
) AS T3
WHERE T1.R1 + T2.R2 + T3.R3 = 33
I tried looking from -10000 to 10000 and there isn't a solution then i watched the youtube video and they say that they already tried up to 10 to the 14th and still no solution.
I did it with python code though when i tried -10000 to 10000...and to optimize of looking for the the C value. First I look at the sum of A cubed and B cubed...the subtract that from 33 and calculate cube root the answer to try to find C in one hit... , this optimizes it a little because then you don't have to loop through all possible values of C.
Since there is no solution for up to 10 to 14th i don't think i can find a solution since just with -10000 to 10000 It took my computer over 2 hours to search. If i looked to 10 to the 14th it would takes like millions of years or something crazy.
You could work with a single table if integers, then do a "self join" using a "cross join".
For R3, you only need to check -ROUND(POW(r1.root_3 + r2.root3, 1/3)). This should significantly speed things up. Also, to make this work, be sure that you have a positive number.
SELECT t1.r1, t2.r2, -ROUND(POW(r1.root_3 + r2.root3, 1/3))
FROM `33_PROBLEM` AS t1
JOIN `33_PROBLEM` AS t2
WHERE t1.root_3 > 0
AND t2.root_3 > -t1.root_3
AND (t1.root_3 + t2.root_3) = ROUND(POW(r1.root_3 + r2.root3, 1/3))

Pair to spend longest time in a single Sql query

I have a long table with following columns:
Id(Serial), FirstName(varchar15), LastName(varchar15), StartDate(date), EndDate(date)
and the entries are like:
* 1, Amar, XoXo, 2009-07-01, 2014-05-23.
* 2, Madhujita, Mami, 2009-03-11, 2014-06-24.
* 3, Akbak Ladar, 2000-04-12, 2009-01-01.
* 4, Abhashuk, Genjin, 2005-06-03, 2005-09-09.
* 5, Sinra, Iao, 2014-01-01, 2014-04-06
and so on till 500 members.
How can I find out which two people have spent most time together and how many days?
Like for the given data Amar and Madhujita have spent the maximum time.
Can this be done in a single query?
Thank You.
Assuming there is one row per person, this is a question of getting the overlap between two spans. The following query uses MySQL syntax to do this (MySQL supports least(), greatest() and limit). This can be done in almost any database, but the exact syntax might vary:
select lt1.firstname, lt1.lastname, lt2.firstname, lt2.lastname,
greatest(0, datediff(least(lt1.EndDate, lt2.EndDate), greatest(lt1.StartDate, lt2.StartDate))) as overlap
from LongTable lt1 cross join
LongTable lt2
where lt1.id <> lt2.id
order by overlap desc
limit 1;
Here is a SQL Fiddle demonstrating it.
Thanx Gordon, I followed your trail and landed up with a query myself with better understanding
select x.firstname as firstname1,x.lastname as surname1,y.firstname as firstname2,y.lastname as surname2
from staff x inner join staff y on
x.startDate <= y.endDate and y.startDate <= x.endDate and x.firstname!=y.firstname and x.surname!=y.surname HAVING MIN(ABS(DATEDIFF(x.startdate,x.endDate)-DATEDIFF(y.startDate,y.endDate)))

SQL/Sybase query group by a substring of a column value

I am making a simple select query with the following result -
select source_uri from image
--
source_uri
"image/30022/A.jpg"
"image/30022/B.jpg"
"image/30022/C.jpg"
"image/30022/D.jpg"
"image/30023/A.jpg"
"image/30023/B.jpg"
"image/30023/C.jpg"
"image/30023/D.jpg"
"image/30024/A.jpg"
"image/30024/B.jpg"
"image/30024/C.jpg"
"image/30024/D.jpg"
I want result like -
source_uri
"image/30022/A.jpg"
"image/30023/B.jpg"
"image/30024/C.jpg"
I tried having a group by clause... but it doesnot group by since the values are different.
--
I am able to use the SUBSTRING_INDEX function in mySQL.
Looking for the exact alternative in Sybase.
If there is always the last 6 i.e D.jpg" characters you need to apply group by then you can use the RIGHT(col,len),Right returns the rightmost len characters from the string str, or NULL if any argument is NULL
select source_uri
from image
GROUP BY RIGHT(source_uri ,6)
RIGHT(str,len)
Other way you need get the part after last / so use SUBSTRING_INDEX
select source_uri
from image
GROUP BY SUBSTRING_INDEX(source_uri ,'/',-1)
SUBSTRING_INDEX(str,delim,count)
EDIT after reading comments
SUBSTRING_INDEX(source_uri ,'/',-1) /* will give you A.jpg*/
Now to get remaining part you can do so
SUBSTRING_INDEX(source_uri ,SUBSTRING_INDEX(source_uri ,'/',-1) ,1) /* will give you image/30022/ */
FOR MySQL -
M Khalid Junaid's answer works great.
FOR Sybase -
I did a lean trick.. not sure how efficient this is -
select source_uri from image
Problem: To extract "image/30022" from "image/30022/a.jpg"
Solution:
1) Got the file length - file_length = CHARINDEX('/', reverse(source_uri))
2) Substring - SUBSTRING(source_uri, 1, LEN(source_uri) - file_length)
select SUBSTRING(source_uri, 1, LEN(source_uri) - file_length) from image
group by SUBSTRING(source_uri, 1, LEN(source_uri) - file_length)

Select data which have same letters

I'm having trouble with this SQL:
$sql = mysql_query("SELECT $menucompare ,
(COUNT($menucompare ) * 100 / (SELECT COUNT( $menucompare )
FROM data WHERE $ww = $button )) AS percentday FROM data WHERE $ww >0 ");
$menucompare is table fields names what ever field is selected and contains data bellow
$button is the week number selected (lets say week '6')
$ww table field name with row who have the number of week '6'
For example, I have data in $menucompare like that:
123456bool
521478bool
122555heel
147788itoo
and I want to select those, who have same word in the last of the data and make percentage.
The output should be like that:
bool -- 50% (2 entries)
heel -- 25% (1 entry)
itoo -- 25% (1 entry)
Any clearness to my SQL will be very appreciated.
I didn't find anything like that around.
Well, keeping data in such format probably not the best way, if possible, split the field into 2 separate ones.
First, you need to extract the string part from the end of the field.
if the length of the string / numeric parts is fixed, then it's quite easy;
if not, you should use regular expressions which, unfortunately, are not there by default with MySQL. There's a solution, check this question: How to do a regular expression replace in MySQL?
I'll assume, that numeric part is fixed:
SELECT s.str, CAST(count(s.str) AS decimal) / t.cnt * 100 AS pct
FROM (SELECT substr(entry, 7) AS str FROM data) AS s
JOIN (SELECT count(*) AS cnt FROM data) AS t ON 1=1
GROUP BY s.str, t.cnt;
If you'll have regexp_replace function, then substr(entry, 7) should be replaced to regexp_replace(entry, '^[0-9]*', '') to achieve the required result.
Variant with substr can be tested here.
When sorting out problems like this, I would do it in two steps:
Sort out the SQL independently of the presentation language (PHP?).
Sort out the parameterization of the query and the presentation of the results after you know you've got the correct query.
Since this question is tagged 'SQL', I'm only going to address the first question.
The first step is to unclutter the query:
SELECT menucompare,
(COUNT(menucompare) * 100 / (SELECT COUNT(menucompare) FROM data WHERE ww = 6))
AS percentday
FROM data
WHERE ww > 0;
This removes the $ signs from most of the variable bits, and substitutes 6 for the button value. That makes it a bit easier to understand.
Your desired output seems to need the last four characters of the string held in menucompare for grouping and counting purposes.
The data to be aggregated would be selected by:
SELECT SUBSTR(MenuCompare, -4) AS Last4
FROM Data
WHERE ww = 6
The divisor in the percentage is the count of such rows, but the sub-stringing isn't necessary to count them, so we can write:
SELECT COUNT(*) FROM Data WHERE ww = 6
This is exactly what you have anyway.
The divdend in the percentage will be the group count of each substring.
SELECT Last4, COUNT(Last4) * 100.0 / (SELECT COUNT(*) FROM Data WHERE ww = 6)
FROM (SELECT SUBSTR(MenuCompare, -4) AS Last4
FROM Data
WHERE ww = 6
) AS Week6
GROUP BY Last4
ORDER BY Last4;
When you've demonstrated that this works, you can re-parameterize the query and deal with the presentation of the results.