I have a table, with a column( called origin) containing values 1 and 0.
Is it possible to create a query in sqlite to convert these values on the fly?
Something like select origin ( convert 1 to read, 0 to not read) from table?
Thanx in advance.
Frits
select case when origin = 1
then 'read'
else 'not read'
end as origin
from your_table
This is possible with a CASE expression:
SELECT CASE origin
WHEN 1 THEN 'read'
WHEN 0 THEN 'not read'
ELSE 'whatever' -- optional
END
FROM MyTable
Related
Thanks again for the help everyone. I went with the script below...
SELECT beginning, end,
(SELECT SUM(sale) FROM sales_log WHERE date BETWEEN beginning AND `end` ) AS sales
FROM performance
and I added a salesperson column to both the performance table and sales_log but it winds up crashing DB Browser. What is the issue here? New code below:
SELECT beginning, end, salesperson
(SELECT SUM(sale) FROM sales_log WHERE (date BETWEEN beginning AND end) AND sales_log.salesperson = performance.salesperson ) AS sales
FROM performance
I believe that the following may do what you wish or be the basis for what you wish.
WITH sales_log_cte AS
(
SELECT substr(date,(length(date) -3),4)||'-'||
CASE WHEN length(replace(substr(date,instr(date,'/')+1,2),'/','')) < 2 THEN '0' ELSE '' END
||replace(substr(date,instr(date,'/')+1,2),'/','')||'-'||
CASE WHEN length(substr(date,1,instr(date,'/') -1)) < 2 THEN '0' ELSE '' END||substr(date,1,instr(date,'/') -1) AS date,
CAST(sale AS REAL) AS sale
FROM sales_log
),
performance_cte AS
(
SELECT substr(beginning,(length(beginning) -3),4)||'-'||
CASE WHEN length(replace(substr(beginning,instr(beginning,'/')+1,2),'/','')) < 2 THEN '0' ELSE '' END
||replace(substr(beginning,instr(beginning,'/')+1,2),'/','')||'-'||
CASE WHEN length(substr(beginning,1,instr(beginning,'/') -1)) < 2 THEN '0' ELSE '' END||substr(beginning,1,instr(beginning,'/') -1)
AS beginning,
substr(`end`,(length(`end`) -3),4)||'-'||
CASE WHEN length(replace(substr(`end`,instr(`end`,'/')+1,2),'/','')) < 2 THEN '0' ELSE '' END
||replace(substr(`end`,instr(`end`,'/')+1,2),'/','')||'-'||
CASE WHEN length(substr(`end`,1,instr(`end`,'/') -1)) < 2 THEN '0' ELSE '' END||substr(`end`,1,instr(`end`,'/') -1)
AS `end`
FROM performance
)
SELECT beginning, `end` , (SELECT SUM(sale) FROM sales_log_cte WHERE date BETWEEN beginning AND `end` ) AS sales
FROM performance_cte
;
From your data this results in :-
As can be seen the bulk of the code is converting the dates into a format (i.e. YYYY-MM-DD) that is usable/recognisable by SQLite for the BETWEEN clause.
Date And Time Functions
I don't believe that you want a join between performance (preformance_cte after reformatting the dates) and sales_log (sales_log_cte) as this will be a cartesian product and then sum will sum all the results within the range.
The use of end as a column name is also awkward as it is a KEYWORD requiring it to be enclosed (` grave accents used in the above).
The above works by using 2 CTE's (Common Table Expresssions), which are temporary tables who'd life time is for the query in which they are used.
The first sales_log_cte is simply the sales_log table but with the date reformatted. The second, likewise, is simply the performace table with the dates reformatted.
If the tables already has suitable date formatting then all of the above could simply be :-
SELECT beginning, `end` , (SELECT SUM(sale) FROM sales_log WHERE date BETWEEN beginning AND `end` ) AS sales FROM performance;
I am having trouble with a query.
Fiddle: https://www.db-fiddle.com/f/JXQHw1VzF7vAowNLFrxv5/1
This is not going to work.
So my question is: What has to be done to get a result when I wanna use both conditions.
(attr_key = 0 AND attr_value & 201326592 = 201326592)
AND
(attr_key = 30 AND attr_value & 8 = 8)
Thanks in advance!
Best regards
One way to check for the presence of some number of key value pairs in the items_attributes table would be to use conditional aggregation:
SELECT i.id
FROM items i
LEFT JOIN items_attributes ia
ON i.id = ia.owner
GROUP BY
i.id
HAVING
SUM(CASE WHEN ia.key = 0 AND ia.value = 201326592 THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN ia.key = 30 AND ia.value = 8 THEN 1 ELSE 0 END) > 0
The trick in the above query is that we scan each cluster of key/value pairs for each item, and then check whether the pairs you expect are present.
Note: My query just returns id values from items matching all key value pairs. If you want to bring in other columns from either of the two tables, you may simply add on more joins to what I wrote above.
My question is about using case statement in where clause to check for date and assign values to columns. My sample code include.
select * from table
where
column 1 > 10 and
case when column 2 = 1
then
column 3<= 10 and column 4 between (1st day of prev month) and (prev month end) or column 5 = '8888-01-01'
else
column 4 between (1st day of this month) and (yesterday)
end ;
when I am running this code. I am getting 3706 syntax error:expected something in between field and '='.
How to fix this ?
A CASE statement will always return a value or NULL (if none of the conditions matches), so you can use it in your WHERE clause. There are a couple ways to format your CASE statement:
Format 1
CASE
WHEN <condition> THEN <some_expression>
WHEN <another_condition> THEN <another_expression>
ELSE <final_expression>
END
-- Example
CASE
WHEN col1 = 10 THEN 'Y'
WHEN col1 = 20 THEN 'N'
ELSE 'N/A'
END
Format 2
CASE <expression>
WHEN <value> THEN <expression>
WHEN <another_value> THEN <another_expression>
ELSE <final_expression>
END
-- Example
CASE col1
WHEN 10 THEN 'Y'
WHEN 20 THEN 'N'
ELSE 'NA'
END
I'm not sure what you're trying to do with your sample code, but it looks more like pseudo-code and will not work as-is. Your CASE statement is not formatted properly and your column references like column 1 will not work that way. If your column is actually named column 1, then you need to put double-quotes around it:
select * from table where "column 1" > 10
Can you please describe a little more clearly what exactly you are trying to do?
A CASE expression can't be used to create some kind of dynamic conditions. Write it as a bunch of AND/OR conditons:
select * from table
where
column 1 > 10 and
(
( column 2 = 1 and
(column 3<= 10 and column 4 between (1st day of prev month) and (prev month end) or column 5 = '8888-01-01')
)
or
column 4 between (1st day of this month) and (yesterday)
);
Double check the logic, the precedence of logical operators is
parenthesis
NOT
AND
OR
I have an sql-select (or insert) which uses the same two parameters several times.
Is there a way to avoid using multiple the same parameter for every "?,?,?,?,..." in the list ?
cursor.execute(statement, list)
I could think of two named parameters but without the possibility of code-injection.
In the example below every left "?" resp. right "?" is the same string. I used the seven counts in one statement in order to get one result.
select count(case (aart like "1%") and (adatum between ? and ?) when 1 then 1 else null end) as AufExt,
count(case (aart like "1%E") and (adatum between ? and ?) when 1 then 1 else null end) as AufExtE,
count(case (aart like "1%K") and (adatum between ? and ?) when 1 then 1 else null end) as AufExtK,
count(case (aart like "2S%") and (adatum between ? and ?) when 1 then 1 else null end) as AufInt,
count(case (eart like "3%") and (edatum between ? and ?) when 1 then 1 else null end) as EntExt,
count(case (eart like "3%K") and (edatum between ? and ?) when 1 then 1 else null end) as EntExtK,
count(case (eart like "2S%") and (edatum between ? and ?) when 1 then 1 else null end) as EntInt
from tabelle
Related question to this problem: It looks as if no index is used in "case". Correct?
The documentation says:
? A question mark that is not followed by a number creates a parameter with a number one greater than the largest parameter number already assigned. [...]
?NNN A question mark followed by a number NNN holds a spot for the NNN-th parameter. [...]
:AAAA A colon followed by an identifier name holds a spot for a named parameter with the name :AAAA. Named parameters are also numbered. [...] To avoid confusion, it is best to avoid mixing named and numbered parameters.
you can also add with clause like this:
with
parms as (select ? as parm1, ? as parm2)
select count(case (aart like "1%") and (adatum between parms.parm1 and parms.parm2) when 1 then 1 else null end) as AufExt
...
I have:
PROCEDURE A
(
inId IN NUMBER,
RC1 OUT SYS_REFCURSOR
) IS
tMessage VARCHAR2(128);
BEGIN
OPEN RC1 FOR
SELECT * FROM
(
SELECT
a.company,
SUM(a.holding_balance) balance
FROM TableNameEntries A
WHERE
A.BATCH_ID = inId
GROUP BY a.company
)
ORDER BY balance DESC ;
EXCEPTION
WHEN OTHERS THEN
tMessage :='Exception ' || SQLCODE || ': ' || SQLERRM;
OPEN RC1 FOR
SELECT tMessage FROM DUAL;
END A;
For the balance column, I have values like -1, 0,1. Currently it's sorted like 1 0 -1, but I don't care about the zeros, so I want it to be like -1,1,0 or 1,-1,0
How do I do it in PL/SQL? I tried:
SELECT
a.company,
SUM(a.holding_balance) balance
FROM REC.CAG_GL_ENTRIES A
WHERE
A.BATCH_ID = 201311
order by case priority when 0 then 2 else 1 END priority
But it's saying PRIORITY is invalid identifier.
How can I get this to work?
Try:
ORDER BY CASE balance
WHEN 0 THEN null
ELSE balance
END
DESC NULLS LAST
there are two ways in your case (second is more common, first is more clear):
SELECT a.company,
SUM(a.holding_balance) balance
FROM REC.CAG_GL_ENTRIES A
WHERE A.BATCH_ID = 201311
order by abs(balance) desc;
SELECT a.company,
SUM(a.holding_balance) balance
FROM REC.CAG_GL_ENTRIES A
WHERE A.BATCH_ID = 201311
order by decode(balance,1,1,-1,1,2);
ORDER BY SIGN(ABS(balance)) DESC, balance
ABS() turns all the negatives to positives. SIGN() turns 0 to 0, >0 to 1 (and <0 to -1). Combined with DESC this puts all the zeros at the end and all the non-zeros above them in no particular order.
Then I sorted by the balance again to order the non-zeros.
You can also use
order by balance * balance desc