How can I do a CASE statement within a distinct clause? - sql

I'm trying to create a Hive view that has the following logic:
create view test.view as
select
distinct(
case
when substr(value_1, 1, 10) < "2016-01-01" then
regexp_extract(value_2,'(?i-sx:\\|([1-9][0-9]{0,3}x[1-9][0-9]{0,3})\\|)',1)
else
split(value_2, '\\|')[5]
end
) as value_3
from test.table;
But when I run this, I get the following output:
FAILED: ParseException line 128:2 cannot recognize input near 'distinct' '(' 'case' in select expression
Does anyone know how I can write this so I don't get an error? Or tell me why this is happening?

distinct is not a function. It's applied on all the columns selected and produces unique combination of all the selected columns.
Try this:
select distinct case
when substr(value_1, 1, 10) < "2016-01-01"
then regexp_extract(value_2, '(?i-sx:\\|([1-9][0-9]{0,3}x[1-9][0-9]{0,3})\\|)', 1)
else split(value_2, '\\|') [5]
end as value_3
from test.table;
So, this:
select distinct (col), col2
is same as:
select distinct col, col2

Related

Can's select between two "select" statements

I need to do statement
SELECT data from result_orders
only if order_state is NULL.
Else I need to do another select statment.
I try this but get error:
ERROR: syntax error at or near "SELECT"
LINE 15: WHEN order_state IS NULL THEN SELECT data from result_order...
SELECT
CASE data
WHEN order_state IS NULL THEN SELECT data from result_orders
ELSE select data from result_orders
END
FROM result_orders
You could use a union here, something like:
WITH cte AS (
SELECT data
FROM result_orders
WHERE order_state IS NULL
)
SELECT * FROM cte
UNION ALL
SELECT ... FROM result_orders WHERE (SELECT COUNT(*) FROM cte) = 0;
In the event that the first query in the union does have records, the second query would return nothing. Should the first query have no records, then the second query would return records if that query matches anything.
the line
WHEN order_state IS NULL THEN SELECT data from result_order
is in the wrong syntax it should look like this
SELECT ISNULL(order_state, result_order)
this means when order_state is null return result_order

Convert from lateral view to case statements in hive

I need to place below code in case statement:
select
count (*)
from db.tab1
lateral view explode(secondary.tertiary) exp as lv
where id IN ('6','1') and array_contains (lv.ci, "1");
I have tried:
select
sum(
case
when id IN ('6','1')
and array_contains ((lateral view explode(secondary.tertiary)).ci, "1")
then 1
else 0
end)
from db.tab1;
But getting error.
select
count(*),
sum(if(..., 1, 0))
from db.tab1
lateral view explode(secondary.tertiary) exp as lv
;
For the provided SQL on table tab1, the actual logic is like:
Explode field secondary.tertiary, alias it as lv, which results in a temporary result set (table) tab2;
A join-like operation to concatenate tab2's fields back to rows in tab1, resulting in another intermediate table tab3;
Select from tab3, upon which where conditions are applied.

Return 1 if value is 0 without CASE statement

I'm trying to find a tidier way of doing the below query so that I'm not duplicating my code.
SELECT CASE WHEN <COMPLICATED CODE THAT RETURNS A SINGLE INT> = 0
THEN 1
ELSE <COMPLICATED CODE THAT RETURNS A SINGLE INT> END
Ideally, I would like something like this using an existing function rather than creating my own:
SELECT ISVALUE(COMPLICATED CODE THAT RETURNS A SINGLE INT,0,1)
You can use apply:
SELECT (CASE WHEN v.val = 0 THEN 1 ELSE v.val END)
FROM . . . CROSS APPLY
(VALUES (<COMPLICATED CODE THAT RETURNS A SINGLE INT>)) v(val);
You could also do a series of functions:
select coalesce(nullif(<COMPLICATED CODE THAT RETURNS A SINGLE INT>, 0), 1)
However, I think apply is clearer. In addition the above will turn NULL values into 1 as well as 0.
You can use a CTE (or a subquery) as
WITH CTE AS
(
SELECT <COMPLICATED CODE THAT RETURNS A SINGLE INT> AS Value
FROM ...
)
SELECT CASE WHEN Value = 0 THEN 1 ELSE Value END
FROM CTE
This way you write the complicated code just once, and then use just the Value column.
You can use IIF:
SELECT IIF(1 = 1, 'true', 'false')
https://learn.microsoft.com/en-us/sql/t-sql/functions/logical-functions-iif-transact-sql
use a sub query, then you can figure out a mathematical formula that acts to give the values you desire, that way you can eliminate actual boolean logic and replace with mathematical functions
an example is
SELECT *,(1 - ceiling(cos(atan(abs(cast(x as float)))) -
floor(cos(atan(abs(cast(x as float))))))) +
x * ceiling(cos(atan(abs(cast(x as float)))) -
floor(cos(atan(abs(cast(x as float)))))) as Computed
FROM
( select 0 as x union SELECT 1 X UNION SELECT -.123 UNION SELECT 9.1 UNION SELECT 67000 union select -1) OQ

SQL Select empty

I have the following code in Oracle 11:
select xmlelement("foo", xmlagg(xmlelement("bar",myValues))) from someTable where rownum = 0; --Changing the rownum from 0 should give me values
The output currently is: <foo></foo>
I would instead like this to return nothing, or null, when no rows are select. Otherwise it'll be a XMLtype with the aggregated data like how I have it above.
How would I be able to achieve this for the case when no rows are selected?
You can use case select:
select case when count (*) != 0 then xmlelement("foo", xmlagg(xmlelement("bar",myValues))) end
You can convert to CLOB using getClobval function and do a comparison.
SELECT
xml
FROM
(
SELECT
xmlelement("foo",xmlagg(xmlelement("bar",myvalues) ) ).getclobval() xml
FROM
sometable
)
WHERE
TO_CHAR(xml) != '<foo></foo>';

Return records based on the result of a function

I have records as follows:
1) BEL
1) MERSEN
A) VISHAY-SPRAGUE
CIRCUIT PARTNERS
BENTEK
CIRCUIT TEST
I want to return a distinct set where if the record has a closing bracket, then remove the entire bracket prefix ( 1) MERSEN becomes MERSEN) otherwise return the record as is. This is an ad hoc, one off query. I've tried something like this.
IF (CHARINDEX(')', (SELECT [MANUFACTURER] FROM [dbo].[QPL_ITMSUPAC_NF]), 1) > 0)
SELECT DISTINCT SUBSTRING([dbo].[QPL_ITMSUPAC_NF].[MANUFACTURER], 4, 99)
FROM [dbo].[QPL_ITMSUPAC_NF]
ELSE
SELECT DISTINCT [dbo].[QPL_ITMSUPAC_NF].[MANUFACTURER]
FROM [dbo].[QPL_ITMSUPAC_NF]
...but get the error:
Subquery returned more than 1 value...
The above was in a procedure.
Thoughts?
Use exists and move the function into the subquery. In this case, the charindex() is equivalent to like ')%':
IF (EXISTS (SELECT 1 FROM [dbo].[QPL_ITMSUPAC_NF] WHERE MANUFACTURER LIKE ')%') )
SELECT DISTINCT SUBSTRING([dbo].[QPL_ITMSUPAC_NF].[MANUFACTURER], 4, 99)
FROM [dbo].[QPL_ITMSUPAC_NF]
ELSE
SELECT DISTINCT [dbo].[QPL_ITMSUPAC_NF].[MANUFACTURER]
FROM [dbo].[QPL_ITMSUPAC_NF]
You could do it with using right function, with taking help from len and charindex functions:
select right(MANUFACTURER,len(MANUFACTURER)-charindex(')',MANUFACTURER))
from QPL_ITMSUPAC_NF
Example:
select right('1)a sample name',len('1)a sample name')-charindex(')','1)a sample name'))
Output:
a sample name
your subquery SELECT [MANUFACTURER] FROM [dbo].[QPL_ITMSUPAC_NF] is returning more than 1 value (a table) but the charindex() function is expecting only 1 value.
SELECT DISTINCT LTRIM(RIGHT(MANUFACTURER,LEN(MANUFACTURER) - CHARINDEX(')',MANUFACTURER)))
FROM QPL_ITMSUPAC_NF
...returned 2552 records
IF (EXISTS (SELECT 1 FROM [dbo].[QPL_ITMSUPAC_NF] WHERE MANUFACTURER LIKE ')%') )
SELECT DISTINCT LTRIM(SUBSTRING([dbo].[QPL_ITMSUPAC_NF].[MANUFACTURER], CHARINDEX(')', [MANUFACTURER], 1) + 1, 99))
FROM [dbo].[QPL_ITMSUPAC_NF]
ELSE
SELECT DISTINCT [dbo].[QPL_ITMSUPAC_NF].[MANUFACTURER]
FROM [dbo].[QPL_ITMSUPAC_NF]
...returned 2495 records.
Close enough for my needs, thanks.