Can you IFERROR Importxml - google-sheets-query

I'm a beginner. I have the formula below which works to pull in the payment date from the table for stocks with a dividend (A9 is the stock ticker), but doesn't for stocks w/out a dividend (no table).
I get:
#value -"unable to parse query string from function query parameter 2: no column:Col6"
I would like it to return 0.00 when there is no dividend. Thanks
=QUERY(IMPORTXML(CONCATENATE("https://www.nasdaq.com/symbol/",A9,"/dividend-history"),"//tbody//tr[1]"),"select Col6 LIMIT 1")

Wrapping in IFERROR should be adequate:
=iferror(QUERY(IMPORTXML(CONCATENATE("https://www.nasdaq.com/symbol/",A9,"/dividend-history"),"//tbody//tr[1]"),"select Col6 LIMIT 1"),"")
but if you must have 0.00 then:
=iferror(QUERY(IMPORTXML(CONCATENATE("https://www.nasdaq.com/symbol/",A9,"/dividend-history"),"//tbody//tr[1]"),"select Col6 LIMIT 1"),"0.00")
Returns Text (for the sake of the required format).

Related

Google Query Language: How to select the min value?

I am doing some web scraping task, and I get prices from a website. The issue is that I would like to get the min between all options. For example: It will looks for one cellphone , which has 8GB and it is unlocked B, but I also need that it returns the min price between all options it finds. Google Query Language: How to select the min value?
This is my sheet. This is the google spreadsheet
=QUERY(ImportJSON(C2),"SELECT Col4,Col20 WHERE Col4 CONTAINS '8GB' AND Col4 CONTAINS 'Unlocked B' LIMIT 1 label Col4'',Col20''",1)
how can I modify that formula so it returns the min price? It's like a loop function, is that possible? regardless its color
For example, I want the function to look for the price, it already does, but I would like to get the lowest price it could finds, instead of the first price it finds and matches with the formula
Google-Query Language Reference
try:
=QUERY(IMPORTJSON(C2),
"select Col4,Col20
where Col4 contains '8GB'
and Col4 contains 'Unlocked B'
order by Col20
limit 1
label Col4'',Col20''", 1)
or:
=QUERY(IMPORTJSON(C2),
"select Col4,min(Col20)
where Col4 contains '8GB'
and Col4 contains 'Unlocked B'
group by Col4
order by min(Col20)
limit 1
label Col4'',min(Col20)''", 1)

MySQL strange behavior when comparing comma-separated string with number

I am experiencing some weird behavior with MySQL. Basically I have a table like this:
ID string
1 14
2 10,14,25
Why does this query pull id 2?
SELECT * FROM exampletable where string = 10
Surely it should be looking for an exact match, because this only pulls id 1:
SELECT * FROM exampletable where string = 14
I am aware of FIND_IN_SET, I just find it odd that the first query even pulls anything. Its behaving like this query:
SELECT * FROM exampletable where string LIKE '10%'
When you compare a numeric and a string value, MySQL will attempt to convert the string to number and match. Number like strings are also parsed. This we have:
SELECT '10,14,25' = 1 -- 0
SELECT '10,14,25' = 10 -- 1
SELECT 'FOOBAR' = 1 -- 0
SELECT 'FOOBAR' = 0 -- 1
SELECT '123.456' = 123 -- 0
SELECT '123.456FOOBAR' = 123.456 -- 1
The behavior is documented here (in your example it is the last rule):
...
If one of the arguments is a decimal value, comparison depends on the
other argument. The arguments are compared as decimal values if the
other argument is a decimal or integer value, or as floating-point
values if the other argument is a floating-point value.
In all other cases, the arguments are compared as floating-point
(real) numbers.

MYSQL replace part of string with condition of char is numeric

Need help with this, as I am stumped with how to set the query update.
I will like to replace occurrences of 10x to 20x where x must be a numeric number. Also the numeric number can occur in any position. And the first two numeric digit of the numeric occurrence must be a 10
eg: tableA - at field colA has the followings:
TOK101s
102YUZ
TAIP103v
ECC10
ECC10a
SCC_103
TD-102b
ZA1104z
Result after the query update should be:
TOK201s
202YUZ
TAIP203v
ECC10
ECC10a
SCC_203
TD-202b
ZA1104z
ECC10 and ECC10a should not be updated since the 3rd char after 10 is not a numeric value.
ZA1104z should not be updated bec the numeric string 1104 does not begin with 10.
Thanks to Barmar and Misaka for:
SQL: search/replace but only the first time a value appears in record
update tableA set colA = IF(INSTR(colA, '10') <> 0, CONCAT(LEFT(colA, INSTR(colA, '10') - 1), '20', SUBSTRING(colA FROM INSTR(colA, '10') + CHAR_LENGTH('10'))), colA) where colA REGEXP '(^|[^0-9])10[0-9]'
The above helped me to get what I wanted.

how to add two millisecond column in mysql

I have table as shown below
gid code time qid
1 123 08:108 15
1 145 11:012 15
1 145 11:216 16
1 123 12:102 16
Now U want to group the 'gid' and add the two time with same code column (ex: i am taking 123, calculating the time (08:108+12:102)/2. Divided by '2' because code 123 appears two time,if it appears three time then divided by 3 this should be dynamic.
I want the result should be
gid code time
1 123 10:105
1 145 11:114
i tried using this query
SELECT sum(time) FROM results group by code; // result in integer values
and SELECT timestamp(sum(time)) FROM results group by code; // result is null
Your time field does not look like it is of the type TIME. A TIME field is in the format HH:MM:SS and doesn't allow to store milliseconds. The MySQL Documentation states that trailing fractions of seconds are allowed in date and time values, but are discarded and not stored.
Your time field looks like it is a varchar and while you can use functions like SUM() or AVG() on that, your notation seconds:milliseconds is wrong.
You can use the following query:
SELECT code,AVG(REPLACE(time,':','.')) FROM results group by code
This replaces the : in your value with ., creating a float number AVG() can handle correctly.
The result:
code AVG(REPLACE(time,':','.'))
123 10.105
145 11.114
Of course this will create more operations on the SQL server. The best way would be to change your column definition to FLOAT and store your seconds and milliseconds as a float:
code time
123 8.108
145 11.012
145 11.216
123 12.102
The result of SELECT code,AVG(time) FROM results GROUP BY code:
code AVG(time)
123 10.1050000190735
145 11.1139998435974
You can use the avg aggregate function on a time column - you'd just need to convert it back to time when you're done, and use time_format if the default format doesn't suit you:
SELECT gid, code, TIME_FORMAT(TIME(AVG(`time`)), '%H-%i.%f')
FROM mytable
GROUP BY gid, code

Need Help on Calculate Percentage of Failure of All Columns in Very Large MySQL Table

I'm having trouble to calculate percentage of failure of every column for my very large MySQL table. Here is an example on how the small table will look like:
Assuming TABLE1 has 5 columns and 100 rows,
CREATE TABLE IF NOT EXIST TABLE1 (id VARCHAR(255) NOT NULL, col1 DOUBLE NOT NULL, col2 DOUBLE NOT NULL, col3 NOT DOUBLE NULL, col4 NOT DOUBLE NULL);
Each column from "col1" to "col4" having its own upper and lower limits and I need to find what is the percentage of failure for "col1" to "col4". Here is the example on how I run my calculation now.
Calculate total number of rows and group by column "id"
SELECT id, COUNT(*) FROM TABLE1 GROUP BY id;
Calculate total number of rows where col1,col2,col3,col4 meets all the limits and group by column "id"
SELECT id, COUNT(*) FROM TABLE1 WHERE (col1 BETWEEN 0 AND 10) AND (col2 BETWEEN 10 AND 20) AND (col3 BETWEEN 20 AND 30) AND (col3 BETWEEN 30 AND 40) GROUP BY id;
Calculate total number of rows that not meet col1 limit
SELECT id, COUNT(col1) FROM TABLE1 WHERE (col1 NOT BETWEEN 0 AND 10) GROUP BY id;
Calculate total number of rows that meet col1 limit but not meet col2 limit, group by "id"
SELECT id, COUNT(col2) FROM TABLE1 WHERE (col1 BETWEEN 0 AND 10) AND (col2 NOT BETWEEN 10 AND 20) GROUP BY id;
Calculate total number of rows that meet col1,col2 limit but not meet col3 limit, group by "id"
SELECT id, COUNT(col3) FROM TABLE1 WHERE (col1 BETWEEN 0 AND 10) AND (col2 BETWEEN 10 AND 20) AND (col3 NOT BETWEEN 20 AND 30) GROUP BY id;
Calculate total number of rows that meet col1,col2,col3 limit but not meet col4 limit, group by "id"
SELECT id, COUNT(col4) FROM TABLE1 WHERE (col1 BETWEEN 0 AND 10) AND (col2 BETWEEN 10 AND 20) AND (col3 BETWEEN 20 AND 30) AND (col3 NOT BETWEEN 30 AND 40) GROUP BY id;
I've written an R script to execute the above 5 queries and combine the result under one data frame. Here is example of the output after processed by R:
id,total_no_rows,yield,col1,col2,col3,col4
CATEGORY1,25,80%,2%,8%,4%,6%,0%
CATEGORY2,25,70%,6%,14%,2%,6%,2%
CATEGORY3,25,90%,5%,0%,5%,0%,0%
CATEGORY4,25,65%,20%,2.5%,2.5%,5%,5%
Now using this method i can get the result pretty quick for small table. However if the table become very large, say 1000 columns and 1 million of rows, the time to complete the calculation is ~ 2 hours, which is extremely long.
Is there anyway i can speed up the calculation?
I've tried indexing but apparently MySQL cannot index 1000 columns.
Tried simultaneous query (10 queries at one time) but no much improvement. (I'm using InnoDB by the way)
I've read some of the posts where users suggests to split the table into smaller chunks to speed up the queries execution. However, my raw data is poorly managed (long story) and all the data dumped into one big text file. So dividing the raw data in smaller chunk will be a challenge.
Please let me know if you have any alternative method to approach this kind of problem.
Edit:
Looks like the the proposal from Mani did save a lot of time to get the result. However the time to complete the query still takes around 10 minutes for very large table (Thousands of column and millions of rows). Is there any way to further improve the query time?
You can use case and find all possible scenario in a single select hit. It will reduce your time.
example
select id, count(*),
sum(case when col1 between 0 and 10 then 1 else 0 end) col1_yes,
sum(case when (col1 not between 0 and 10) and (col2 between 0 and 10) then 1
else 0 end) col1no_col2yes
from table
group by id;