multiple columns with multiple values in where clause - teradata

I am executing a query which has multiple columns in where clause which has multiple values. I know that in SQL you can use IN condition to satisfy and get the correct output. What is the way to do in teradata?
my code in Oracle looks like this:
select td.country_code,td.phone_num
from telephone_directory td
where (td.country_code, td.phone_num) in ((91,1234567890),(44,1020304050),(1,998877446655))
This prints out the exact result i.e. 3 rows
My query in teradata looks like this
select country_code ,phone_num
from telephone_directory
where (country_code in (91, 44, 1) and phone_num in( 1234567890, 1020304050, 998877446655)
This however returns more rows:
country_code phone_num
91 1234567890
91 1020304050
44 1020304050
1 998877446655
NOTE: The combination of country_code and phone num is not unique.
Is there a way to filter it out in teradata like that in ORACLE?

As far as I know, Teradata does not support the "expanded" where clause syntax as you can do in Oracle; you need to specify the criteria as compound expressions:
select country_code ,phone_num
from telephone_directory
where (country_code=91 and phone_num=1234567890)
or (country_code=44 and phone_num=1020304050)
or (country_code=1 and phone_num=998877446655)

select USER_TYPE,USER_ID
from USER_TABLE
where (USER_TYPE || USER_ID) in (('F6713'),('S1178'),('M5715'),('F8341'),('F1284'))

Logically the results from Teradata that you are seeing are correct. You have one phone number with multiple country codes. The following SQL should produce the result you are looking to see:
select td.country_code,td.phone_num
from telephone_directory td
where (td.country_code, td.phone_num)
in ( SELECT 91 AS country_code_
, 1234567890 AS phone_num_
UNION
SELECT 44 AS country_code_
, 1020304050 as phone_num_
UNION
SELECT 1 as country_code_
, 998877446655 as phone_num_
);
This could also be re-written using the WITH clause or a combination of AND statements grouped together with parenthesis to produce the correct results.

Related

SELECT the matching condition value along with the result from a multiple condition WHERE clause on the same column

I think this is a pretty simple question but I can't figure out the right search terms to search this. This question is the most similar I could find, but it's the opposite of what I'm trying to do.
I have a query like this :
SELECT * FROM table WHERE column LIKE "val1%" OR column LIKE "val2%" OR column LIKE "val3%", ...so..on..and..on
Since it's an OR, only some of them will give matches from the column.
How can I return the matching LIKE clause with the query itself ? Like this :
SELECT *, (val1 or val2 or val3 - the matched val) FROM table WHERE column LIKE "val1%" OR column LIKE "val2%" OR column LIKE "val3%", ...so..on..and..on
Since the matching is by wildcard "%", I need to get the exact value that got the match.
If the table is this :
name
age
Mike
1
John
2
Michael
3
Milinda
4
And if the query is :
SELECT *, (the matched value) FROM table WHERE name LIKE "Mik%" OR name LIKE "Mic%" OR name LIKE "mia%"
It would return :
name
age
match
Mike
1
Mik
Michael
3
Mic
Is this possible purely with an SQLite query ? I know this can be done later after obtaining the results, but want to remove that redundancy since SQLite will already be matching anyway.
Note: The table is very large. 100,000+ rows. So performance is a big factor to get result as fast as possible. Also the OR conditions can be 5 or 10 or 15+
Create a CTE with all the match strings that you have and join to the table:
WITH cte(match) AS (VALUES ('Mik'), ('Mic'))
SELECT t.*, c.match
FROM tablename t INNER JOIN cte c
ON t.name LIKE c.match || '%'
See the demo.
You may use a case expresssion. See working fiddle below:
Schema (SQLite v3.30)
CREATE TABLE my_table (
`name` VARCHAR(7),
`age` INTEGER
);
INSERT INTO my_table
(`name`, `age`)
VALUES
('Mike', '1'),
('John', '2'),
('Michael', '3'),
('Milinda', '4');
Query #1
SELECT
*,
CASE
WHEN name LIKE "Mik%" THEN "Mik"
WHEN name LIKE "Mic%" THEN "Mic"
WHEN name LIKE "mia%" THEN "mia"
END as matched_value
FROM
my_table
WHERE
name LIKE "Mik%" OR
name LIKE "Mic%" OR
name LIKE "mia%";
name
age
matched_value
Mike
1
Mik
Michael
3
Mic
View on DB Fiddle

How to cast a column into decimal of varying significant digits in Oracle

I have a column that is stored in ###0.0000000000 format. In a report I'm generating I need it to only show a few significant digits. Problem is the number needed changes based on the product with a default of 2. There's a column in another table that provides the required digits per each product.
I've tried a few things so far but it seems to not like it and throws a syntax error.
Cast(A.Price as Numeric(10,coalesce(B.Sig_Digits,2)))
That threw an error so I tried making the coalesce part a column and aliasing it in case the coalesce broke it, and that didn't work either. Round will take a column as an argument but I don't want it to round. Other than an ugly
case when Sig_digits = 1 then to_char(price,'###0.0') when Sig_digits = 2...
etc. what other options are there? This is a very large report, with 100+ columns and a few million rows so I'd prefer to not do the case when.
Use TO_CHAR with RPAD to add 0s to the end of the format model to the correct number of decimal places:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( value, sig ) AS
SELECT 123.456789, 2 FROM DUAL UNION ALL
SELECT 123456789.123456789, 7 FROM DUAL;
Query 1:
SELECT TO_CHAR( value, RPAD( 'FM999999999990.', sig + 15, '0' ) )
FROM table_name
Results:
| TO_CHAR(VALUE,RPAD('FM999999999990.',SIG+15,'0')) |
|---------------------------------------------------|
| 123.46 |
| 123456789.1234568 |

Creating a HAVING COUNT(column) > 2 clause in pyDAL

I have the following pyDAL table:
market = db.define_table(
'market',
Field('name'),
Field('ask', type='double'),
Field('timestamp', type='datetime', default=datetime.now)
)
I would like to use the expression language to execute the following SQL:
SELECT * FROM market
GROUP BY name
ORDER BY timestamp DESCENDING
HAVING COUNT(name) > 1
I know how to do the ORDER BY and the GROUP BY:
db().select(
db.market.ALL,
orderby=~db.market.timestamp,
groupby=db.market.name
)
but I do not know how to do a count within a having clause even after reading the section in the web2py book on the HAVING clause.
The count() function returns an expression which can be used both as a field in the select query, and to build an argument to the query's having parameter. The Grouping and counting section from the web2py manual has a few hints on this topic.
The following code will give the desired result. The row objects will hold both the market objects and their respective row counts.
count = db.market.name.count()
rows = db().select(
db.market.ALL,
count,
groupby=db.market.name,
orderby=~db.market.timestamp,
having=(count > 2)
)

SQLite Select from one table or from another

I would like to know how to make a single query to select something from one table or from another. For example I have Table A with the aID=2 and Table B with bID=3. So how to make the query to return the id from table A or table B for a given id = 3?
Thanks in advance
If you do not know which table to use before you're running the query, you can combine multiple queries with UNION, provided that you're selecting the same number of columns:
SELECT something FROM A WHERE aID = 3
UNION ALL
SELECT something FROM B WHERE bID = 3
If you do not want to duplicate the WHERE condition, you can use a nested query and apply the WHERE to its result:
SELECT something
FROM (SELECT aID as ID, something FROM A
UNION ALL
SELECT bID , something FROM B)
WHERE ID = 3

SQLite returns single row even though I am not using GROUP BY

I have the following SQLite database
I expect there will be 3 rows of result being returned, if I make the following query.
SELECT name, sum(heart) FROM test_table;
However, even though I am not using GROUP BY, only 1 row is being returned.
C:\Users\yan-cheng.cheok\Desktop>sqlite3.exe
SQLite version 3.7.13 2012-06-11 02:05:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .restore abc
sqlite> SELECT name, sum(heart) FROM test_table;
Record3|102
I am expecting result :
Record1|102
Record2|102
Record3|102
As in convientional SQL, if I do not use GROUP BY, every individual rows will be returned.
http://www.w3schools.com/sql/sql_groupby.asp
Is there anything I can make all 3 rows returned?
Try this you can use cross join
SELECT a.name, b.totalHeart
FROM test_table a,
(
SELECT SUM(heart) totalHeart
FROM test_table
) b
This behaviour is documented:
If the SELECT statement is an aggregate query without a GROUP BY clause, then each aggregate expression in the result-set is evaluated once across the entire dataset. Each non-aggregate expression in the result-set is evaluated once for an arbitrarily selected row of the dataset. The same arbitrarily selected row is used for each non-aggregate expression. Or, if the dataset contains zero rows, then each non-aggregate expression is evaluated against a row consisting entirely of NULL values.
You could do this:
sqlite> select a.name, b.s from abc as a, (select sum(heart) as s from abc) as b;
Record1|102
Record2|102
Record3|102

Resources