I have this query
SELECT
CASE WHEN (enddate is NULL) THEN "Current" ELSE CONCAT(
to_date(from_unixtime(startdate * 24 * 60 * 60)),
' - ',
to_date(from_unixtime(enddate * 24 * 60 * 60))
) END as Current
FROM
table
I'm getting this error cannot recognize input near 'as' 'Current' ',' in selection target but when I take out as Current out it works. I just want to alter the column name and not have it displayed _c1 or something like that.
Current is a keyword in Hive, you need to change your alias or declare it using graves (`) as follow
SELECT
CASE WHEN (enddate is NULL) THEN "Current" ELSE CONCAT(
to_date(from_unixtime(12 * 24 * 60 * 60)),
' - ',
to_date(from_unixtime(12 * 24 * 60 * 60))
) END as `Current`
from ...
current is the reserved keyword in hive so if you have any column name which is matching with any of he reserved keyword in hive then you need to enclose that column with ``(back-tick).
Related
I have PostgreSQL SQL that should look for a backslash in a column called source_username and if it finds the backslash, it should replace the current value of the source_username column with the same value without the characters before the backslash.
For example:
before source_username: domain\username
after source_username: username
with os_user as (
select source_username from itpserver.managed_incidents mi;
),
osUserWithoutDomain as (
select (
case when (select * from os_user) ilike '%\\%' and (select position('-' in (select * from os_user))>= 1) and (select length((select * from os_user)) != (select position('-' in (select * from os_user))) + 1)
then (
select substring(
(select * from os_user),(select position('\' in (select * from os_user)) + 1),(select length((select * from os_user)) - 1)
))
else ((select * from os_user))
end
)
)
UPDATE itpserver.managed_incidents SET source_username = replace(source_username, (select * from os_user), (select * from osUserWithoutDomain)),
description = replace(description , (select * from os_user), (select * from osUserWithoutDomain)),
additional_info = replace(additional_info , (select * from os_user), (select * from osUserWithoutDomain)),
typical_behavior = replace(typical_behavior , (select * from os_user), (select * from osUserWithoutDomain)),
raw_description = replace(raw_description , (select * from os_user), (select * from osUserWithoutDomain));
This SQL works fine when I have only one row in the table.
If I have multiple rows, I need to specify the row that I want to work with by adding where id = <id>
I wish to iterate all the relevant rows (all the rows that source_username contains backslash) and on each row to perform the SQL above.
I tried to do this with LOOP:
create or replace function fetcher()
returns void as $$
declare
emp record;
begin
for emp in select *
from itpserver.managed_incidents
order by id
limit 10
loop
raise notice '%', emp.id;
<my sql> where id = emp.id
end loop;
end;
$$language plpgsql;
select fetcher();
However, I get an error because I don't think it likes the 'with' statement.
Any idea how can I do it?
It's far simpler than that. You need to use the SUBSTR and STRPOS functions. Take a look at the results of this query.
https://dbfiddle.uk/9-yPKn6E
with os_user (source_username) as (
select 'domain\username'
union select 'mydomain\joe'
union select 'janet'
)
select u.source_username
, strpos(u.source_username, '\')
, substr(u.source_username, strpos(u.source_username, '\') + 1)
from os_user u
source_username
strpos
substr
domain\username
7
username
janet
0
janet
mydomain\joe
9
joe
What you need is:
UPDATE itpserver.managed_incidents
SET source_username = substr(source_username, strpos(source_username, '\') + 1)
, description = replace(description , source_username, substr(source_username, strpos(source_username, '\') + 1))
, additional_info = replace(additional_info , source_username, substr(source_username, strpos(source_username, '\') + 1))
, typical_behavior = replace(typical_behavior , source_username, substr(source_username, strpos(source_username, '\') + 1))
, raw_description = replace(raw_description , source_username, substr(source_username, strpos(source_username, '\') + 1));
This is based on lengthy experience with SQL Server and some quick document searches for Postgresql. The UPDATE statement may not work as I expect.
SQL by design/default works on complete data sets. It thus eliminates LOOPS entirely from the language - they are not needed. (Well not quite there are recursive queries). Your task is accomplished in a single update statement with a simple regular expression. See documentation String Functions:
update managed_incidents
set source_username = regexp_replace(source_username,'.*\\(.*)','\1');
Demo here.
Main Take away: Drop procedural logic terminology (for, loop, if then, ...) from your SQL vocabulary. (you choose alternatives with case.)
I am getting an error
Error converting data type varchar to numeric
when I run this code:
SELECT CONCAT('$', ' ', a * 0.05 + b * 12) AS value
Variables a and b are defined as money datatype
Try casting the arithmetic expression to text before including it as a parameter in the CONCAT() function:
SELECT CONCAT('$', ' ', CAST(a * 0.05 + b * 12 AS varchar(20))) AS value;
I have a column in SQL server and I want to add 7 for the words which begin by a and add 8 for the words which begin by t.
Here is my column:
add-on
above
tv
their
french
And I want this:
7add-on
7above
8tv
8their
french
I am looking for a query which could do that.
Thank you very much!
You can use left() & do the concatenation :
select t.*,
(case left(col, 1)
when 'a' then concat(7, col)
when 't' then concat(8, col)
else col
end)
from table t;
Use a case expression with substring to get the results you require.
select concat(
(case when substring(col,1,1)='a' then '7'
when substring(col,1,1)='t' then '8'
end
)
,col
) as modified_col
from table
You need 2 update queries. Try like:
UPDATE myTable SET myColumn='7'+myColumn WHERE myColumn LIKE 'a%';
UPDATE myTable SET myColumn='8'+myColumn WHERE myColumn LIKE 't%'
Use CASE statement to check the first char, returned by SUBSTRING function, and calculate a prefix to add to your data:
select
case substring(column, 1, 1)
when 'a' then '7'
when 't' then '8' else '' end + column as NewColumn
from table
In sql server 2008 :
select
case when substring(column,1,1)='a' then ( '7 ' + column)
case when substring(column,1,1)='t' then ( '8 ' + column)
else column end as column from table
In sql server 2012 or above :
select
case when substring(column,1,1)='a' then concat( '7 ',column)
case when substring(column,1,1)='t' then concat( '8 ',column)
else column end as column from table
I am trying to cap particular fields so that they don't exceed a particular value.
For example, something like this would suffice, where I can specify that a field should not exceed 8:
SELECT (
cap(t.MondayHrs,8)
+ cap(t.TuesdayHrs,8)
+ cap(t.WednesdayHrs,8)
+ cap(t.ThursdayHrs,8)
+ cap(t.FridayHrs,8)
) as TotalHours
If MondayHrs = 7, then it should be added to TotalHours as 7.
If MondayHrs = 10, then it should be added to TotalHours as 8 (my capped value)
Is there anything built into T-SQL that could facilitate this?
create function Cap (#Value float,#maxValue float) Returns float
as
begin
Declare #Result float
if #Value > #maxValue select #Result=#Maxvalue else select #Result=#Value
Return #Result
end;
usage
Select dbo.Cap(1,10),dbo.Cap(11,10)
Try...
select least(t.MondayHrs,8)
+ least(t.TuesdayHrs,8)
+ least(t.WednesdayHrs,8)
+ least(t.ThursdayHrs,8)
+ least(t.FridayHrs,8)
) as TotalHours
An alternate idea would be to use CASE. For example:
SELECT (
(CASE WHEN t.MondayHrs > 8 THEN 8 ELSE t.MondayHrs END)
+ (CASE WHEN t.TuesdayHrs > 8 THEN 8 ELSE t.TuesdayHrs END)
) as TotalHours
You can write a function for that like MySQL GREATEST.
Then you could do something like
select greatest(some_col, 8) +
greatest(other_col, 8) +
...
from your_table
I am trying to figure out a good way to return a string 'name' of a range in which a given number falls. Ranges are spans of 1000, so the first range is '0000-0999', the second is '1000-1999' etc. For example, given the number 1234, I want to return the literal string '1000-1999'.
It seems to me that I could maintain a reference table with these ranges, like this
--create & populate temp table with ranges
create table #ranges (st int,en int)
go
insert into #ranges values(0,999)
insert into #ranges values(1000,1999)
insert into #ranges values(2000,2999)
go
--example query
select replace(str(st,4),' ','0') + '-' + replace(str(en,4),' ','0') as TheStringIWant
from #ranges
where 1234 between st and en
...but it seems to me that the ranges should be able to be determined from the given number itself, and that I shouldn't need the (redundant) reference table (or, for that matter, a function) just for this.
It also seems to me that I should be able to figure this out with just a bit of brain power, except that I've just had 2 beers in quick succession this evening...
Another way;
select case when value / 1000 < 1
then '0000-0999'
else cast(value / 1000 * 1000 as varchar(16)) + '-' + cast(value / 1000 * 1000 + 999 as varchar(16))
end
You can use mathematical functions to avoid using the temp table:
SELECT 1234,
RIGHT('0000' + CAST(FLOOR(1234/1000.0) * 1000 AS VARCHAR(11)),4)
+ '-'
+ RIGHT('0000' + CAST( (FLOOR(1234/1000.0) * 1000) + 999 AS VARCHAR(11)),4)
In the shell, I can use integer-arithmetic to cut off the 234, and calculate the string with a simple formular, however it wouldn't produce 0000-0999 but 0-999 for the first 1000.
v=1234
echo $(((v/1000)*1000))-$(((v/1000)*1000+999))
1000-1999
I don't know how to adapt it to tsql - whether possible at all.
declare #range int;
set #range = 1000;
select replace(str(st,4),' ','0') + '-' +
replace(str(st + #range,4),' ','0') as TheStringIWant
from (
select st = v / #range * #range
from (select v = 1234) s
) s