Is there a conditional where statement in SQLite? - sql

I have a Todo application with a database for the todos. It contains a column done which will be set to false or true. Now I want to filter the data by all or unfinished. So either done is irrelevant or it has to be false.
I am using SQLite3 in a TypeScript application. Currently I do this by using string templates but I'd prefer an SQL-based solution.
db.prepare(`
select
rowid as id,
title,
description
from todo
${selectAll ? '' : 'where done = 0'}
limit ?
offset ?
`).all(limit, offset);
My idea was to use the CASE clause but it seems not to work around the WHERE clause.
Is there any better solution?
selectAll is a TypeScript variable that is set depending on the query parameters of the app.
Output when selectAll is false
id | title | description | done
1 | Clean the kitchen | as the title says... | 1
2 | Do the shopping | potatoes, tomatoes | 0
3 | Program stuff | Todo app | 1
Output when selectAll is true
id | title | description | done
2 | Do the shopping | potatoes, tomatoes | 0

You can use boolean logic:
where ? = '' or done = 0

Related

Condition with SQL

I've come to see you for a question. Is there a condition in SQL that allows you to do that:
IF(sup = void) {
}
Database
id | name | lastname | city | mail | number | picture | ...
1 | kiwi | kiwi | USA | kiwi#gmail.com | 0000000000 | default.img | (vide)
SELECT * FROM your_table WHERE sup IS NULL
https://www.w3schools.com/sql/sql_null_values.asp
Update after reading your comment.
$test = $db->query("SELECT * FROM ressource_view WHERE ID = 1")
Will give you the result of your query. Be careful as there could be multiple rows returned.
To fetch the first row
$row = $result->fetch_array()
And then to check if the sup column of your row is null you can use:
if(is_null($row['sup']))
{
}
Or this will have the same effect
if($row['sup'] === NULL)
{
}
But best to tag your question with PHP, MySQL. Your problem seems to be more on the PHP side and someone else could provide a better answer.

How to get column names from a query?

I have a specific query with joins and aliases, and I need to retrieve columns name for a REST request in Talend.
I'm using Talend Open Studio for Data Integration 6.2 and I've got an Oracle 11g database with a read-only account. I can execute scripts with Talend, For example the query:
select
u.name as "user",
f.name as "food",
e.rate
from
Users as u
join Eval as e on u.user_id = e.user_id
join Food as f on e.food_id = f.food_id
where
1 = 1
should give the following result:
+------+--------+------+
| user | food | rate |
+------+--------+------+
| Baba | Donuts | 16.0 |
| Baba | Cheese | 20.0 |
| Keke | Pasta | 12.5 |
| Keke | Cheese | 15.0 |
+------+--------+------+
And I try to get the columns (in the right order) as follows by using scripts or Talend:
+--------+
| Column |
+--------+
| user |
| food |
| rate |
+--------+
Is there a way to query the Oracle database to get the columns or using talend to retrieve them?
UPDATE
Thanks to Marmite Bomber, a duplicate has been identified here for the Oracle approach. Now we need a Talend approach to the problem.
You can try this on a tJavaRow, following your DBInput component :
for (java.lang.reflect.Field field: row1.getClass().getDeclaredFields()) {
context.columnName = field.getName();
System.out.println("Field name is " + context.columnName );
}
Spotted on talend help center here : https://community.talend.com/t5/Design-and-Development/resolved-how-to-get-the-column-names-in-a-data-flow/td-p/99172
You can extend this, and put the column list on your outputflow :
//add this inside the loop, and 'columnNames' as an output row in tJavaRow schema
output_row.columnNames+=context.columnName+";";
With a tNormalize after tJavaRow, you shoud get the expected result.
Here´s a link to an oracle community thread which should answer your question
community.oracle.com
I am not able to write a comment, so posting this as an answer:
SELECT column_name
FROM all_tab_cols
WHERE table_name = 'table_name_here'

Dynamically Modify Internal Table Values by Data Type

This is a similar question to the one I posted last week.
I have an internal table based off of a dictionary structure with a format similar to the following:
+---------+--------+---------+--------+---------+--------+-----+
| column1 | delim1 | column3 | delim2 | column5 | delim3 | ... |
+---------+--------+---------+--------+---------+--------+-----+
| value1 | | | value 1 | | | value 1 | | | ... |
| value2 | | | value 2 | | | value 2 | | | ... |
| value3 | | | value 3 | | | value 3 | | | ... |
+---------+--------+---------+--------+---------+--------+-----+
The delim* columns are all of type delim, and the typing of the non-delimiter columns are irrelevant (assuming none of them are also type delim).
The data in this table is obtained in a single statement:
SELECT * FROM <table_name> INTO CORRESPONDING FIELDS OF TABLE <internal_table_name>.
Thus, I have a completely full table except for the delimiter values, which are determined by user input on the selection screen (that is, we cannot rely on them always being ,, or any other common delimiter).
I'd like to find a way to dynamically set all of the values of type delim to some input for every row.
Obviously I could just hardcode the delimiter names and loop over the table setting all of them, but that's not dynamic. Unfortunately I can't bank on a simple API.
What I've tried (this doesn't work, and it's such a bad technique that I felt dirty just writing it):
DATA lt_fields TYPE TABLE OF rollname.
SELECT fieldname FROM dd03l
INTO TABLE lt_fields
WHERE tabname = '<table_name>'
AND as4local = 'A'
AND rollname = 'DELIM'.
LOOP AT lt_output ASSIGNING FIELD-SYMBOL(<fs>).
LOOP AT lt_fields ASSIGNING FIELD-SYMBOL(<fs2>).
<fs>-<fs2> = '|'.
ENDLOOP.
ENDLOOP.
Once again, I'm not set in my ways and would switch to another approach altogether if I believe it's better.
Although I still believe you're barking up the wrong tree with the entire approach, You have been pointed in the right direction both here and in the previous question
ASSIGN COMPONENT <fs2> OF STRUCTURE <fs> TO FIELD-SYMBOL(<fs3>). " might just as well continue with the write-only naming conventions
IF sy-subrc = 0.
<fs3> = '|'.
ENDIF.

Language fallback with database content in OpenCart

I've just (6 months+) started learning all the web languages, mostly within OpenCart's framework. Right now I'm trying to get language fallback to work with database content.
The objective is to check for an empty field in id.title and if so choose the default language_id=1.
The language_id comes from a GET request invoked by the frontend user.
The table description looks like this:
------------------------------------------------------
| information_id | language_id | title | description |
------------------------------------------------------
| 3 | 1 | policy | policy desc |
------------------------------------------------------
| 4 | 1 | about | about desc |
------------------------------------------------------
| 4 | 2 | | |
------------------------------------------------------
| 5 | 1 | terms | terms desc |
------------------------------------------------------
| 6 | 1 | comp | comp desc |
------------------------------------------------------
As you can see language_id=2 has no title nor description (inserted by sql, not oc's admin). In this case I want to get the row with the default language=1.
I've tried using CASE but the results are always empty. The problem I can't find a solution for this is to check the title field next to the requested language_id.
I've also tried to first check the field before doing a SELECT, but no success.
SELECT DISTINCT *
FROM information_description id
WHERE id.information_id = '4'
AND id.language_id = (CASE WHEN id.title = '' THEN '1' ELSE '2' END);
Any help would be appreciated.
Here You have two options. Either do this by subselects or once per save/update walk through all the information descriptions and update the missing languages with the texts from the default ones.
The first solution could be:
SELECT id.information_id, id.language_id, id.description,
CASE WHEN id.title IS NOT NULL /* or CASE WHEN id.title <> '' - depending on the real value in DB when it's empty */
THEN id.title
ELSE (SELECT title FROM information_description WHERE language_id = 1)
AS title
FROM information_description id
WHERE id.language_id = 2
I would call such query only in the case when the language ID differs from the default one. Since this may look like working solution I don't like it simply because it increases the DB effort.
Instead of this I recommend to simply update Your missing data in similar way (this could be done maybe only once per life and you are done):
UPDATE information_description id SET
id.title = (SELECT title FROM information_description WHERE language_id = 1 AND information_id = id.information_id)
WHERE id.language_id <> 1
AND id.title IS NULL
for title and
UPDATE information_description id SET
id.description = (SELECT description FROM information_description WHERE language_id = 1 AND information_id = id.information_id)
WHERE id.language_id <> 1
AND id.description IS NULL
for description fields...

connecting three tables in one query

I have the following tables
mixes
mid | date | info
1 | 2009-07-01 | no info yet
music-review
mid | song | buy
1 | Example - Example | http://example.com
2 | Exam - Exam | http://example.com
tracklist
tid | mid | mrid
1 | 1 | 1
2 | 1 | 2
is it possible to have an SQL query where you can link these all into one?
so my results would turn out like:
date | info | tracklist
2009-07-01 | no info yet | Example - Example http://example.com, Exam - Exam http://example.com
or however this result would be returned... or would this need to be a two sql querys where i get the MID from the mixes and then do a query to get the tracklist from that?
For MySQL:
SELECT mixes.date, mixes.info,
GROUP_CONCAT(DISTINCT music-review.song + ' ' + music-review.buy
ORDER BY music-review.mid ASC SEPARATOR ', ')
FROM mixes
JOIN tracklist ON tracklist.mid = mixes.mid
JOIN music-review ON music-review.mrid = tracklist.mrid
GROUP BY mixes.date, mixes.info
this works as adapted from mherren:
SELECT mixes.`date`, mixes.info,
CONCAT(GROUP_CONCAT(DISTINCT `music-review`.song , ' ' , `music-review`.`mid`
ORDER BY `tracklist`.`tid` ASC SEPARATOR ', ')) as `tracklist`
FROM mixes
JOIN tracklist ON tracklist.`mid` = mixes.`mid`
JOIN `music-review` ON tracklist.`mrid` = `music-review`.`mid`
WHERE `mixes`.`date`='2009-07-01'
GROUP BY mixes.`date`, mixes.info;
it fixes a blurb issue i was getting but, one thing is that group_concat has a max limit set at 1024 this can be altered tho by
SET GLOBAL group_concat_max_len=4096
I left so many comments, I thought it would be more helpful to suggest a revision to your architecture as an answer. However, I do think mherren has already competently addressed your actual concern, so while votes are appreciated, I don't think this should be considered as the the right "answer".
I think you need to reconsider how you have arranged the data. Specifically, you have a table for "music-review" that seems out of place while at the same time you refer to "mixes" and "tracklists" which seems a bit redundant. I imagine you want a one-to-many relationship where "mixes" refers to the information about the mix, like when it was created, the user who created it, etc. While "tracklist" is the list of songs within the "mix". What if you tried this:
#song-info
song_id | artist | title | online-store
1 | The Airheads | Asthma Attack! | example.com/?id=123
2 | The Boners | Bite the Boner | example.com/?id=456
3 | Cats in Heat | Catching a Cold | example.com/?id=789
4 | Dirty Djangos | Dig these Digits | example.com/?id=147
#mixes
mix_id | date | info
1 | 2009-07-01 | no info yet
2 | 2009-07-02 | no info yet
#mix_tracklist
mix_id | song_id
1 | 1
1 | 2
2 | 2
2 | 3
Now you can have a list of available mixes, and if a user selects a mix, another query for the actual songs.
Trying to put all of the song data into one column should only be done if the results require that info right away or if there is a condition within the query itself that is conditional to the results of that sub-query. If you simply want to output a list of mixes with the track list for each one, you are better of doing the query for each mix based on the mix index. So in the case of php outputting HTML, you would go with:
$mixes = mysql_query("SELECT * FROM mixes WHERE date > '$last_week'");
while($mix = mysql_fetch_assoc($mixes)) {
$mix_id = $mix['mix_id'];
$mix_date = date('m/d/Y', strtotime($mix['mix_id']));
$mix_info = $mix['mix_id'];
echo <<<EOT
<h2 class="mix_number">$mix_number</h2>
<p class="mix_date">$mix_date</p>
<p class="mix_info">$mix_info</p>
<h3>Track Listing:</h3>
<ul class="tracklist">
EOT;
$tracks = mysql_query("SELECT song.artist artist,
song.title title,
song.online-store url
song.song_id
FROM song-info song
JOIN mix_tracklist tracks ON (tracks.song_id = song.song_id)
WHERE tracks.mix_id = '$mix_id'
ORDER_BY song_id);
while ($track = mysql_fetch_assoc($tracks)) {
$artist = $track['artist'];
$song_name = $track['title'];
$song_url = $track['url'];
echo <<<EOT
<li>$artist – $song_name</li>
EOT;
}
echo "</ul>";
}