select statement for specific value sqlite - sql

could you help me to make a select query for this case,
recently i'm looking for a way to implement expandable list view that fill the data from database, but i'm not found a proper example yet,
and this i'm thinking about another way,
i have 2 table :
table1 :
+------------+----------+
| id_table1 | Item |
+------------+----------+
| 1 | Item1 |
| 2 | Item2 |
| 3 | Item3 |
| 4 | Item2.1 |
| 5 | Item2.2 |
| 6 | Item3.1 |
| 7 | Item3.2 |
+------------+----------+
table 2 : id_table2.table2 = id_table1.table1 and table2.id_table = id_table1.table1
+------------+----------+
| id_table2 | id_table |
+------------+----------+
| 2 | 4 |
| 2 | 5 |
| 3 | 6 |
| 3 | 7 |
+------------+----------+
and with some select query the result will be :
Item1
Item2
Item2.1 //with space
Item2.2 //with space
Item3
Item3.1 //with space
Item3.2 //with space

You can do what you want to do with these tables, a la the following:
select id_table1, Item from table1
where not exists (
select id_table2
from table2 where id_table1=id_table)
union
select id_table2, child.Item
from table1 parent, table2, table1 child
where table2.id_table2=parent.id_table1
and table2.id_table=child.id_table1;
The first query finds those items that are "parent" items. The second one finds those that are children. (You might have some issues ordering later on. And this assumes only two levels at the moment.) But it is not a very clear way to do it. At least I would suggest column names that indicate what you are doing, e.g:
table1: ViewItem. Columns: id, Item
table2: ItemChild. Columns: parentId, childId
You will find quite a few hits on this type of question, hierarchical menus being one such application.

Related

array clustering with unique identifier for file datasets

I have a dataset with big int array column in s3 and I want to filter rows efficiently based on array values. I know we can use gin index in sql table but need solution to work on s3 dataset. I am planning to use cluster id for each combinations of elements in array (as their cardinality is not huge. max 2500) and then store it as new column on which later on filter can applied.
Example,
Table A
+------+------+-----------+
| Col1 | Col2 | Col3 |
+------+------+-----------+
| 1 | 101 | [123,234] |
| 2 | 102 | [123] |
| 3 | 103 | [234,345] |
+------+------+-----------+
I am trying to add new column like,
Table B (column Col3 will be removed from actual schema)
+------+------+-----------+-----------+
| Col1 | Col2 | Col3 | Cid |
+------+------+-----------+-----------+
| 1 | 101 | [123,234] | 1 |
| 2 | 102 | [123] | 2 |
| 3 | 103 | [234,345] | 3 |
+------+------+-----------+-----------+
and there will be another table of mapping for col3 and Cid like,
Table C
+-----------+-----+
| Col3 | Cid |
+-----------+-----+
| [123,234] | 1 |
| [123] | 2 |
| [234,345] | 3 |
+-----------+-----+
This table C will be added a new entry if a new combination is created and B will be updated if any array element gets added or removed. Goal is to be able to filter out records from Table A based on values in array column efficiently. Queries like
123 = Any(Col3) can be served as Cid = 2 or queries like [123, 345] = Any(Col3) can be served as Cid in (2,3).
Is there any better way to do solve this problem?
Also I am thinking of creating required combinations at runtime to limit number of combinations. Is it a good idea to create minimum combinations?
In Postgres, you can create the table and use join to calculate the values:
create table array_dim as
select col3 as arr, row_number() over (order by min(col1)) as array_id
from t
group by col3;
You can then add the new column:
select a.*, ad.array_id
from a join
array_dim ad
on a.col3 = ad.arr

SELECTing Related Rows Based on a Single Row Match

I have the following table running on Postgres SQL 9.5:
+---+------------+-------------+
|ID | trans_id | message |
+---+------------+-------------+
| 1 | 1234567 | abc123-ef |
| 2 | 1234567 | def234-gh |
| 3 | 1234567 | ghi567-ij |
| 4 | 8902345 | ced123-ef |
| 5 | 8902345 | def234-bz |
| 6 | 8902345 | ghi567-ij |
| 7 | 6789012 | abc123-ab |
| 8 | 6789012 | def234-cd |
| 9 | 6789012 | ghi567-ef |
|10 | 4567890 | abc123-ab |
|11 | 4567890 | gex890-aj |
|12 | 4567890 | ghi567-ef |
+---+------------+-------------+
I am looking for the rows for each trans_id based on a LIKE query, like this:
SELECT * FROM table
WHERE message LIKE '%def-234%'
This, of course, returns just three rows, the three that match my pattern in the message column. What I am looking for, instead, is all the rows matching that trans_id in groups of messages that match. That is, if a single row matches the pattern, get all the rows with the trans_id of that matching row.
That is, the results would be:
+---+------------+-------------+
|ID | trans_id | message |
+---+------------+-------------+
| 1 | 1234567 | abc123-ef |
| 2 | 1234567 | def234-gh |
| 3 | 1234567 | ghi567-ij |
| 4 | 8902345 | ced123-ef |
| 5 | 8902345 | def234-bz |
| 6 | 8902345 | ghi567-ij |
| 7 | 6789012 | abc123-ab |
| 8 | 6789012 | def234-cd |
| 9 | 6789012 | ghi567-ef |
+---+------------+-------------+
Notice rows 10, 11, and 12 were not SELECTed because there was not one of them that matched the %def-234% pattern.
I have tried (and failed) to write a sub-query to get the all the related rows when a single message matches a pattern:
SELECT sub.*
FROM (
SELECT DISTINCT trans_id FROM table WHERE message LIKE '%def-234%'
) sub
WHERE table.trans_id = sub.trans_id
I could easily do this with two queries, but the first query to get a list of matching trans_ids to include in a WHERE trans_id IN (<huge list of trans_ids>) clause would be very large, and would not be a very inefficient way of doing this, and I believe there exists a way to do it with a single query.
Thank you!
This will do the job I think :
WITH sub AS (
SELECT trans_id
FROM table
WHERE message LIKE '%def-234%'
)
SELECT *
FROM table JOIN sub USING (trans_id);
Hope this help.
Try this:
SELECT ID, trans_id, message
FROM (
SELECT ID, trans_id, message,
COUNT(*) FILTER (WHERE message LIKE '%def234%')
OVER (PARTITION BY trans_id) AS pattern_cnt
FROM mytable) AS t
WHERE pattern_cnt >= 1
Using a FILTER clause in the windowed version of COUNT function we can get the number of records matching the predefined pattern within each trans_id slice. The outer query uses this count to filter out irrelevant slices.
Demo here
You can do this.
WITH trans
AS
(SELECT DISTINCT trans_id
FROM t1
WHERE message LIKE '%def234%')
SELECT t1.*
FROM t1,
trans
WHERE t1.trans_id = trans.trans_id;
I think this will perform better. If you have enough data, you can do an explain on both Sub query and CTE and compare the output.

SQL: query to show how many users have each property (grouped)

I'm new to SQL and can't seem to ask the right question, as in every time I formulate it differently I end up with the same results: A query that groups data by several properties (users that share more than one property).
I'm writing a JSP-based website on the Glassfish server, and manage the database from MS Access.
What I'm interested in, is basically grouping by several distinct properties. Say I have a table that shows which items a user has. Something like this:
id | name | item1 | item2 | item3 | item4 |
--------------------------------------------------
1 | name1 | yes | yes | | yes |
----+-------+---------+--------+--------+--------+
2 | name2 | yes | | | yes |
----+-------+---------+--------+--------+--------+
3 | name3 | | yes | | yes |
----+-------+---------+--------+--------+--------+
4 | name4 | yes | yes | | yes |
----+-------+---------+--------+--------+--------+
5 | name5 | | | yes | yes |
.
.
.
The query that I need, would return the following:
ItemID | Number of users with this item
-----------------------------------------
item1 | 3
item2 | 3
item3 | 1
item4 | 5
I don't see how GROUP BY can be used here, as the result I'm looking for basically demands that the properties of the original table, will now appear as the values in each row of the resulting table.
What is the right query, and how such operation is called (it's not grouping by each property, it's something else...)?
I can't see how you could do this in Access if you need it to work on any table, but if you know the table structure you can design a query like:
select 'item1' as ItemID, count(*) as [Number of users with this item]
from myTable
where item1 = 'Yes'
union
select 'item2', count(*)
from myTable
where item2 = 'Yes'
union
....
and so on.
You could do an aggregate query that returns 1 record with the count under each Item field. Assuming these are Yes/No type fields:
SELECT Sum(IIf([Item1],1,0)) AS Count1, Sum(IIf([Item2],1,0)) AS Count2, Sum(IIf([Item3],1,0)) AS Count3, Sum(IIf([Item4],1,0)) AS Count4 FROM Table1;
Your data structure is not normalized. Instead of 4 Item fields should be one Item field with the item code. Normalized structure would allow option for GROUP BY or CROSSTAB queries.
id | name | item |
----------------------+
1 | name1 | 1 |
----+-------+---------+
2 | name1 | 2 |
----+-------+---------+
3 | name1 | 4 |
----+-------+---------+
4 | name2 | 1 |
----+-------+---------+
5 | name2 | 4 |
Can emulate the normalized structure with a UNION query. There is no designer for UNION, must type into SQLView of query builder.
SELECT ID AS SourceRecID, [Name] AS User, 1 AS Item, "Item1" AS Source FROM tablename
UNION SELECT ID, [Name], 2, "Item2" FROM tablename
...;
Now use that query in another query to do the aggregate GROUP BY calcs. Or use it as the source for a report. A report will allow display of raw detail data as well as summary calcs.

difference between select * and select table name

This is the basic question about sql statements.
What is the difference between
SELECT * FROM "Users"
and
SELECT "Users".* FROM "Users"
[TableName].[column] is usually used to pinpoint the table you wish to use when two tables a present in a join or a complex statement and you want to define which column to use out of the two with the same name.
It's most common use is in a join though, for a basic statement such as the one above there is no difference and the output will be the same.
In your case there is no difference. It emerges, when you are selecting from multiple tables. * takes data from all the tables, TABLE_NAME.* - all the data from this table. Suppose, we have a database with 2 tables:
mysql> SELECT * FROM report;
+----+------------+
| id | date |
+----+------------+
| 1 | 2013-05-01 |
| 2 | 2013-06-02 |
+----+------------+
mysql> SELECT * FROM sites_to_report;
+---------+-----------+---------------------+------+
| site_id | report_id | last_run | rows |
+---------+-----------+---------------------+------+
| 1 | 1 | 2013-05-01 16:20:21 | 1 |
| 1 | 2 | 2013-05-03 16:20:21 | 1 |
| 2 | 2 | 2013-05-03 14:21:47 | 1 |
+---------+-----------+---------------------+------+
mysql> SELECT
-> *
-> FROM
-> report
-> INNER JOIN
-> sites_to_report
-> ON
-> sites_to_report.report_id=report.id;
+----+------------+---------+-----------+---------------------+------+
| id | date | site_id | report_id | last_run | rows |
+----+------------+---------+-----------+---------------------+------+
| 1 | 2013-05-01 | 1 | 1 | 2013-05-01 16:20:21 | 1 |
| 2 | 2013-06-02 | 1 | 2 | 2013-05-03 16:20:21 | 1 |
| 2 | 2013-06-02 | 2 | 2 | 2013-05-03 14:21:47 | 1 |
+----+------------+---------+-----------+---------------------+------+
mysql> SELECT
-> report.*
-> FROM
-> report
-> INNER JOIN
-> sites_to_report
-> ON
-> sites_to_report.report_id=report.id;
+----+------------+
| id | date |
+----+------------+
| 1 | 2013-05-01 |
| 2 | 2013-06-02 |
| 2 | 2013-06-02 |
+----+------------+
In the case of example given by you, there is no difference between them when it comes to semantics.When it comes to performance it might be too little... just parsing two different length strings....
But, it is only true for the example given by you. Where as in queries where multiple tables are involved tableName.* disambiguate the table from which table we want to select all columns.
Example:
If you have two tables TableA and TableB. Let's suppose that they have column with same names that is Name. If you want to specify from which table you want to select Name column. Table-name qualifier helps.
`select TableA.Name, TableB.Name where TableA.age=TableB.age`
That's all I can say.
The particular examples specified would return the same result and have the same performance. There would be no difference in that respect, therefore.
However, in some SQL products, difference in interpreting * and alias.* has effect, in particular, on what else you can add to the query. More specifically, in Oracle, you can mix an alias.* with other expressions being returned as columns, i.e. this
SELECT "Users".*, SomeColumn * 2 AS DoubleValue FROM "Users"
would work. At the same time, * must stand on its own, meaning that the following
SELECT *, SomeColumn * 2 AS DoubleValue FROM "Users"
would be illegal.
For the examples you provided, the only difference is in syntax. What both of the queries share is that they are really bad. Select * is evil no matter how you write it and can get you into all kinds of trouble. Get into the habit of listing the columns you want to have included in your result set.

How to query two different fields from a table, and make it appear in the same row?

I have two tables. Say:
This is table 1
+--------+-----------------------+
| stuff | foreing | foreing2 |
+--------+-----------------------+
| bazzzz | 555 | 666 |
+--------+-----------------------+
This is table 2
+-----------------------+
| id_table | values |
+-----------------------+
| 555 | Foo |
+-----------------------+
| 666 | Bar |
+-----------------------+
What I want is a SQL query that gives me a row with this info:
+--------+-----------------------+
| stuff | value1 | value2 |
+--------+-----------------------+
| bazzzz | Foo | Bar |
+--------+-----------------------+
This is what I tried to do, but actually it returns two rows, which is not what I want:
SELECT table1.stuff,
table2.values as value1,
table2.values as value2
WHERE table1.foreing = table2.id_table
OR table1.foreing2 = table2.id_table
Since you need to match two columns with the same child table... you need to refer the child table twice...
Select table1.Stuff, B.Vales as Value1, C.Values as Value2
From table1, table2 as B, table2 as C
Where table1.foreing = B.id_table and table1.foreing2 = C.id_table
You shall have to make inner queries like this:
SELECT table1.stuff,
(select table2.values as value1 where table2.id_table=table1.foreing),
(select table2.values as value2 where table2.id_table=table1.foreing2)
from table1