SQlite multiple IDs linking one to another table - sqlite

I have one table containing rows with information about dealers and unique IDs.
id name
1 dealer1
2 dealer2
The other table contains products which are sometimes available at multiple dealers.
name dealerids
product1 1, 2
product2 2
Now I would like to query all dealers a product is available at, but I don't know how. I tried something like:
SELECT * FROM dealers WHERE id IN (SELECT dealerids FROM products WHERE name = "product1")
which didn't work. I'm in C# and dealerids is based on a string and stored as TEXT in the database. I tried "'1', '2'" and "1, 2", both didn't work for me.
I'm quiet new to SQL so is there a way to achieve what I want using the TEXT datatype?

Well, that's strange way to store the values in a database - as a string separated by commas. But if it's really the case and you can not change this to multiple lines where each record corresponds to one dealer id , you probably can try this:
select * from dealers where exists (select 1 from products where name = "product1" and dealerids like
dealers.id || ',' || '%') or exists
(select 1 from products where name = "product1" and dealerids like '%' || ', ' || dealers.id || ',%')
or exists
(select 1 from products where name = "product1" and dealerids like '%, ' || dealeris.id)
The first clause is taking care of the case where desired delearid is the first one in the string, the second clause is for the case when it's in the middle, and the third one is for the ending id.

A normalized database would look something like this, in your scenario.
// table_dealer
id name
1 dealer1
2 dealer2
// table_product
id title
1 product1
2 product2
//table_associate
id product_id dealer_id
1 1 1
1 2 1
Now I would like to query all dealers a product is available at, but I don't know how. I tried something like
//searching by product_id
select dealer_id from table_associate where product_id = X
Use JOIN query to get data from these 3 tables.

Related

How to split these records into individual new ones?

I want to search if a string exists in column2 (site_id) then put that string in a new table with the value of its before column in that row. The table has only 2 columns and the site_id column may have many 5-word strings that I want.
I want to get all of the the specific site id's. For example: E7089 or E7459 (I need all of them and the first word is random like E or T or etc and the four digits are variable).
The first row is with one ticket_id and many site_ids. I only need site ids like:g1231 or g1236 and not the addresses in parentheses:
ticket_id
site_id
sss-bb-12312312-12312
g1231(afsdgf-sdgsdgdg), g1236(sdfsdgsdg), g3212(asdfas-dfsd), b2311(asdasd), b3213(asdfsdf)
And make it like this:
ticket_id
site_id
sss-bb-12312312-12312
g1231
sss-bb-12312312-12312
g3211
sss-bb-12312312-12312
g1236
sss-bb-12312312-12312
b2311
sss-bb-12312312-12312
b3213
I can find the 5-word site id's with regexp [A-Z]\d{1,4}, but I can't extract and insert them into a new row. My code :
DROP TABLE IF EXISTS test2;
CREATE TABLE if NOT EXISTS test2
(
Ticket_id varchar,
site_id varchar
);
INSERT INTO test2
SELECT ticket_id, site_id
FROM TEST
WHERE site_id regexp '[A-Z]\d{1,4}';
This will find the site_id's and insert rows that match. I don't want that. How to convert the first one to the second?
Current db :
column1
column2
ticket1
many site ids
ticket2
many site ids
I want it to be :
column1
column2
ticket1
id
ticket1
id
ticket1
id
ticket1
id
ticket2
id
ticket2
id
ticket2
id
The tickets do not need any change except getting copied into new rows with their assigned site_id.
There are multiple site_ids for each ticket that need to be separated to new rows.
It needs to be done in SQLite db browser (unfortunately no Python).
You need a recursive CTE to split the site_id column of the table test1 and SUBSTR() function to take the first 5 chars to insert in the table test2:
WITH cte AS (
SELECT ticket_id, '' site_id, site_id || ',' s
FROM test1
UNION ALL
SELECT ticket_id,
SUBSTR(s, 0, INSTR(s, ',')),
SUBSTR(s, INSTR(s, ',') + 1)
FROM cte
WHERE s <> ''
)
INSERT INTO test2 (ticket_id, site_id)
SELECT ticket_id, SUBSTR(TRIM(site_id), 1, 5)
FROM cte
WHERE site_id <> '';
See the demo.

Cannot replace a string with several random strings taken from another table in sqlite

I'm trying to replace a placeholder string inside a selection of 10 random records with a random string (a name) taken from another table, using only sqlite statements.
i've done a subquery in order to replace() of the placeholder with the results of a subquery. I thought that each subquery loaded a random name from the names table, but i've found that it's not the case and each placeholder is replaced with the same string.
select id, (replace (snippet, "%NAME%", (select
name from names
where gender = "male"
) )
) as snippet
from imagedata
where timestamp is not NULL
order by random()
limit 10
I was expecting for each row of the SELECT to have different random replacement every time the subquery is invoked.
hello i'm %NAME% and this is my house
This is the car of %NAME%, let me know what you think
instead each row has the same kind of replacement:
hello i'm david and this is my house
This is the car of david, let me know what you think
and so on...
I'm not sure it can be done inside sqlite or if i have to do it in php over two different database queries.
Thanks in advance!
Seems that random() in the subquery is only evaluated once.
Try this:
select
i.id,
replace(i.snippet, '%NAME%', n.name) snippet
from (
select
id,
snippet,
abs(random()) % (select count(*) from names where gender = 'male') + 1 num
from imagedata
where timestamp is not NULL
order by random() limit 10
) i inner join (
select
n.name,
(select count(*) from names where name < n.name and gender = 'male') + 1 num
from names n
where gender = 'male'
) n on n.num = i.num

Converting a string to be used in in-clause Teradata

I have a string like this ('car, bus, train')
I want to convert it to be used in an in-clause. Basically I want to convert it to
('car','bus','train'). Please how do I do this in Teradata
I don't know how you are getting data like that, but if you have no control over that, you can use STRTOK_SPLIT_TO_TABLE.
select t.* from table (strtok_split_to_table(1,'car, bus, train',',')
returns (outkey integer,tokennum integer,resultstring varchar(25))) as t
Run by itself, that gives you:
outkey tokennum resultstring
1 1 car
1 2 bus
1 3 train
You can use that as a derived table and join it to the table you want to filter by. Something like:
select
<your table>.*
from
<your table>
inner join (select t.* from table (strtok_split_to_table(1,'car, bus, train',',')
returns (outkey integer,tokennum integer,resultstring varchar(25))) as t) dt
on yourtable.yourcolumn = dt.resultstring
here is the another way of spliting the input for n number of commas and use IN clause.
SELECT regexp_substr('car,bus,train','[^,]+',1,day_of_calendar) fields
FROM sys_calendar.calendar
WHERE day_of_calendar <= (CHAR('car,bus,train') - CHAR(oreplace('car,bus,train',',','')))+1;
Output of the Query
fields
~~~~~~~~
bus
car
train
Here is the systax to use in where clause
SELECT * FROM <your table>
WHERE yourtable.requiredColumn in
(
SELECT regexp_substr('car,bus,train','[^,]+',1,day_of_calendar) fields
FROM sys_calendar.calendar
WHERE
day_of_calendar <= (CHAR('car,bus,train') - CHAR(oreplace('car,bus,train',',','')))+1
);
Basically what we are doing here is splitting the string for each comma and below function is calculating number of commas in the string
(CHAR('car,bus,train') - CHAR(oreplace('car,bus,train',',','')))+1

Counting 2 Columns from Separate Tables Between 2 Dates

I have a query that Counts 2 columns from 2 separate tables using subqueries, which works. Now I have to implement into this query the ability to filter out these results based on the Date of a Call Record. I will post the query in which I am working with:
SELECT (m.FirstName || " " || m.LastName) AS Members,
(
SELECT count(CallToLineOfficers.MemberID)
FROM CallToLineOfficers
WHERE CallToLineOfficers.MemberID = m.MemberID
)
+ (
SELECT count(CallToMembers.MemberID)
FROM CallToMembers
WHERE CallToMembers.MemberID = m.MemberID
) AS Tally
FROM Members AS m, Call, CallToMembers, CallToLineOfficers
Join Call on CallToMembers.CallID = Call.CallID
and CallToLineOfficers.CallID = Call.CallI
WHERE m.FirstName <> 'None'
-- and Call.Date between '2017-03-21' and '2017-03-22'
GROUP BY m.MemberID
ORDER BY m.LastName ASC;
Ok, so table Call stores the Date and its PK is CallID. Both CallToLineOfficers and CallToMembers are Bridge Tables that also contain only CallID and MemberID. With the current query, where the Date is commented out, that Date range should only return all names, but a count of 1 should appear under 1 person's name.
I have tried joining Call.CallID with both Bridge Tables' CallIDs without any luck, though I think this is the right way to do it. Could someone help point me in the right direction? I am lost. (I tried explaining this the best I could, so if you need more info, let me know.)
UPDATED: Here is a screenshot of what I am getting:
Based on the provided date in the sample, the new results, with the Date, should be:
Bob Clark - 1
Rob Catalano - 1
Matt Butler - 1
Danielle Davidson - 1
Jerry Chuska - 1
Tom Cramer - 1
Everyone else should be 0.
At the moment, the subqueries filter only on the member ID. So for any member ID in the outer query, they return the full count.
To reduce the count, you have to filter in the subqueries:
SELECT (FirstName || " " || LastName) AS Members,
(
SELECT count(*)
FROM CallToLineOfficers
JOIN Call USING (CallID)
WHERE MemberID = m.MemberID
AND Date BETWEEN '2017-03-21' AND '2017-03-22'
)
+ (
SELECT count(*)
FROM CallToMembers
JOIN Call USING (CallID)
WHERE MemberID = m.MemberID
AND Date BETWEEN '2017-03-21' AND '2017-03-22'
) AS Tally
FROM Members AS m
WHERE FirstName <> 'None'
ORDER BY LastName ASC;

Zipping rows with the same "key" while joining tables

I have two tables, one with objects, one with properties of the objects. Both tables have a personal ID and a date as "key", but since multiple orders of objects can be done by one person on a single day, it doesn't match well. I do know however, that the entries are entered in the same order in both tables, so it is possible to join on the order, if the personID and date are the same.
This is what I want to accomplish:
Table 1:
PersonID Date Object
1 20-08-2013 A
2 13-11-2013 B
2 13-11-2013 C
2 13-11-2013 D
3 21-11-2013 E
Table 2:
PersonID Date Property
4 05-05-2013 $
1 20-08-2013 ^
2 13-11-2013 /
2 13-11-2013 *
2 13-11-2013 +
3 21-11-2013 &
Result:
PersonID Date Object Property
4 05-05-2013 $
1 20-08-2013 A ^
2 13-11-2013 B /
2 13-11-2013 C *
2 13-11-2013 D +
3 21-11-2013 E &
So what I want to do, is join the two tables and "zip" the group of entries that have the same (PersonID,Date) "key".
Something called "Slick" seems to have this (see here), but I'd like to do it in SQLite.
Any advice would be amazing!
You are on the right track. Why not just do a LEFT JOIN between the tables like
select t2.PersonID,
t2.Date,
t1.Object,
t2.Property
from table2 t2
left join table1 t1 on t2.PersonID = t1.PersonID
order by t2.PersonID
Use a additional column to make every key unique in both tables. For example in SQLite you could use RowIDs to keep track of the order of insertion. To store this additional column in the database itself might be useful for other queries as well, but you do not have to store this.
First add the column ID to both tables, the DDL queries should now look like this: (make sure you do not add the primary key constraint until both tables are filled.
CREATE TABLE table1 (
ID,
PersonID,
Date,
Object
);
CREATE TABLE table2 (
ID,
PersonID,
Date,
Property
);
Now populate the ID column. You can adjust the ID to your liking. Make sure you do this for table2 as well:
UPDATE table1
SET ID =(
SELECT table1.PersonID || '-' || table1.Date || '-' || count( * )
FROM table1 tB
WHERE table1.RowID >= tB.RowID
AND
table1.PersonID == tB.PersonID
AND
table1.Date == tB.Date
);
Now you can join them:
SELECT t2.PersonID,
t2.Date,
t1.Object,
t2.Property
FROM table2 t2
LEFT JOIN table1 t1
ON t2.ID = t1.ID;

Resources