iterating through "IN" clause in SQL without a loop - sql

Is there a way to iterate through the "IN" clause in a SQL statement without having to implement some sort of loop?
My example is:
SELECT *
FROM store_table
WHERE store_a IN (1,2,3,4,5,6,7,8,9,10);
Instead of having to list out all of the stores, is there a way to list write some sort of code that it will look like this:
SELECT *
FROM store_table
WHERE store_a IN (1,2,...10);
I understand that the above is not real SQL syntax but for examples sake I wanted to use it in that manner. I know that if you wanted to view all stores there are many different ways, syntactically to do so but I am just worried for the first 100 or the last 20 or etc....
The reason I am asking this is because if you had 1000 stores and you wanted to see the first 500, you would have some pretty long and annoying code.
Any help is appreciated!

If you want to see the first 500 stores, then use:
select st.*
from (select st.*
from store_table st
order by store_a
) st
where rownum <= 500;
This assumes one row per "store", which makes sense for a table with that name.
In Oracle 12C+, you can use fetch first 500 rows only and not have to use a subquery.

Use between instead of the in operator, e.g.
SELECT *
FROM store_table
WHERE store_a BETWEEN 1 AND 10

Related

SQL exercise - implicit join

Good afternoon everyone,
I'm a beginner, trying to solve an exercise and can't understand why as result I get nothing but the headers.
I'm using IBM Db2.
Consider 2 tables:
CHICAGO_PUBLIC_SCHOOLS: (COMMUNITY_AREA_NAME | SAFETY_SCORE)
CENSUS_DATA: (COMMUNITY_AREA_NAME | PER_CAPITA_INCOME)
Exercise:
[Without using an explicit JOIN operator] Find the Per Capita Income of the Community Area which has a Safety Score of 1
my code:
SELECT COMMUNITY_AREA_NAME, PER_CAPITA_INCOME
FROM CENSUS_DATA
where COMMUNITY_AREA_NAME IN
(SELECT COMMUNITY_AREA_NAME FROM CHICAGO_PUBLIC_SCHOOLS
WHERE SAFETY_SCORE=1)
Thanks a lot to whoever will help me understanding
EDIT:
A little add on based on the first two comments I received, hoping this might be helpful. the safety score shouldn't be an issue, since the following code works properly:
SELECT COMMUNITY_AREA_NAME FROM CHICAGO_PUBLIC_SCHOOLS
WHERE SAFETY_SCORE=1
First, you should qualify all column names in any query that has more than one table reference:
SELECT cd.COMMUNITY_AREA_NAME, cd.PER_CAPITA_INCOME
FROM CENSUS_DATA cd
WHERE cd.COMMUNITY_AREA_NAME IN
(SELECT cps.COMMUNITY_AREA_NAME
FROM CHICAGO_PUBLIC_SCHOOLS cps
WHERE cps.SAFETY_SCORE = 1
);
Here are possibilities that I can readily think of to explain why this query would return no rows:
Either table has no rows.
CHICAGO_PUBLIC_SCHOOLS has no rows that match SAFETY_SCORE = 1.
Any rows with SAFETY_SCORE = 1 have area names that are not in the census table.
COMMUNITY_AREA_NAME does not match between the two tables.
You have not provided sample data or a fiddle. Here are some ideas for debugging:
For the first possibility, run COUNT(*) on the two tables.
For the second, just run the subquery to see if it returns any rows.
For the third, run the subquery and manually check to see if the names match in the table.
For the fourth, you have to consider strings that look the same but are different -- often because of hidden characters.

Group By Using Wildcards in Big Query

I have this query:
SELECT SomeTableA.*
FROM SomeTableB
LEFT JOIN SomeTableA USING (XYZ)
GROUP BY SomeTableA.*
I know that I cannot do the GROUP BY part with wildcards. At the same time, I don't really like listing all the columns (can be up to 20) manually.
Could this be added as new feature? Or is there any way how to easily get the list of all 20 columns from SomeTableA for the GROUP BY part?
If you really have the exact query shown in your question - then try below instead - no grouping required
#standardSQL
SELECT DISTINCT *
FROM `project.dataset.tableA`
WHERE xyz IN (SELECT xyz FROM `project.dataset.tableB`)
As of Group By Using Wildcards in Big Query this sounds more like grouping by struct which is not supported so you can submit feature request if you want - https://issuetracker.google.com/issues/new?component=187149&template=0

Maximum number of expressions in a list is 1000

I 'm trying to select 170k records from a oracle database, there are some how to avoid this error? or any way to improve this query ?
thanks.
select sr.RELATED_PON, srsi.VALID_VALUE
from SERV_REQ sr
inner join SERV_REQ_SI_VALUE srsi
on sr.DOCUMENT_NUMBER = srsi.DOCUMENT_NUMBER
inner join SERV_ITEM si
on si.SERV_ITEM_ID = srsi.SERV_ITEM_ID
and si.STATUS = '6'
where srsi.VALUE_LABEL = 'unitAddress'
and srsi.VALID_VALUE in ('1682511819',
'1682575135',
'1682580326'
... more than 150k here!
)
Lamak is correct: This really looks like a list that belongs in a table.
However, if this is not convenient for whatever reason, you must break the IN clause into chunks of no more than 1000 elements each. Happily, this is pretty trivial: You insert ) OR ( scri.VALID_VALUE in every 1000 items.
Unfortunately, you're soon going to bump into the max size of a query string. (For Oracle, I think that's 32K)... but seriously consider a temp table or something.

Access SQL Query - Top 25 containing /images/

I'm a university student (thus a beginner) with some Access tasks to do, but I need help because so far it does not provide the desired result.
I have a table Table1 containing web log records. My field of interest is "cs-uri-stem", as it contains all the URL GET requests.
I want to select the TOP 25 images (records must contain /images/ in the "cs-uri-stem" field). So far I tried the following, with no success:
SELECT TOP 25
FROM Table 1
WHERE "cs-uri-stem"="cs-uri-stem"
HAVING [/images/];
An alert window keeps appearing saying that the SELECT request is not correct, but I don't know if this is caused by the fact that the Access is in Spanish in my university.
Thanks in advance!
Possible answer to my question, provided with Siyual and MCP_infiltrator's help [Thanks again!]:
SELECT TOP 25
Table1.[cs-uri-stem],
Count(Table1.[cs-method]) AS TotalHits
FROM Table1
WHERE (((Table1.[cs-uri-stem]) Like '*/images*'))
GROUP BY Table1.[cs-uri-stem]
ORDER BY Count(Table1.[cs-method]) DESC`
This will provide a top25 list of only the visited images, with no duplicates, instead of all the URLs.
There are several things wrong with your query, but this should work for what you need:
SELECT TOP 25 Images
FROM Table1
WHERE cs-uri-stem Like '%/images/%'
As for the what/why things are wrong...
For your Select statement, you aren't specifying any fields that you're wanting to get. I'm assuming by your question that you have a field named images that you're wanting to get back. If it's some other field, change that, or just use SELECT TOP 25 * to get everything.
Your From clause has a space in the table name.
Your Where clause makes no sense. This is where you need to be putting your logic for your query. In this case, you want anything that has /images/ in the cs-uri-stem field. Like is the operator you need to use here.
Finally, your Having is just plain wrong. It's not used correctly, nor is it even in the right context.
SELECT TOP 25 *
FROM TABLE1
WHERE CS-URI-STEM LIKE "*/images*"
This will select the top 25 records and all columns from the table where the cs-uri-stem has /images in it. When you use the * that is telling the db that you want all the columns of the table to be pulled for viewing.
Here is a link describing some of it
See Here: Select Top n in MS-Access
Another link
from office.microsoft.com
I would create three queries:
query1:
SELECT Images
FROM Table1
WHERE cs-uri-stem Like '*/images/*'
query2:
select images, count(images) as image_count
from query1 as q
group by images
query3:
select top 25 *
from query2
order by image_count desc
query3 should have the 25 results that you're interested in.
SELECT TOP 25 * FROM Table1 WHERE cs-uri-stem LIKE '%/images/%'
http://www.w3schools.com/sql/sql_like.asp

LIMIT in FoxPro

I am attempting to pull ALOT of data from a fox pro database, work with it and insert it into a mysql db. It is too much to do all at once so want to do it in batches of say 10 000 records. What is the equivalent to LIMIT 5, 10 in Fox Pro SQL, would like a select statement like
select name, address from people limit 5, 10;
ie only get 10 results back, starting at the 5th. Have looked around online and they only make mention of top which is obviously not of much use.
Take a look at the RecNo() function.
FoxPro does not have direct support for a LIMIT clause. It does have "TOP nn" but that only provides the "top-most records" within a given percentage, and even that has a limitation of 32k records returned (maximum).
You might be better off dumping the data as a CSV, or if that isn't practical (due to size issues), writing a small FoxPro script that auto-generates a series of BEGIN-INSERT(x10000)-COMMIT statements that dump to a series of text files. Of course, you would need a FoxPro development environment for this, so this may not apply to your situation...
Visual FoxPro does not support LIMIT directly.
I used the following query to get over the limitation:
SELECT TOP 100 * from PEOPLE WHERE RECNO() > 1000 ORDER BY ID;
where 100 is the limit and 1000 is the offset.
It is very easy to get around LIMIT clause using TOP clause ; if you want to extract from record _start to record _finish from a file named _test, you can do :
[VFP]
** assuming _start <= _finish, if not you get a top clause error
*
_finish = MIN(RECCOUNT('_test'),_finish)
*
SELECT * FROM (SELECT TOP (_finish - _start + 1) * FROM (SELECT TOP _finish *, RECNO() AS _tempo FROM _test ORDER BY _tempo) xx ORDER BY _tempo DESC) yy ORDER BY _tempo
**
[/VFP]
I had to convert a Foxpro database to Mysql a few years ago. What I did to solve this was add an auto-incrementing id column to the Foxpro table and use that as the row reference.
So then you could do something like.
select name, address from people where id >= 5 and id <= 10;
The Foxpro sql documentation does not show anything similar to limit.
Here, adapt this to your tables. Took me like 2 mins, i do this waaaay too often.
N1 - group by whatever, and make sure you got a max(id), you can use recno() to make one, sorted correctly
N2 - Joins N1 where the ID = Max Id of N1, display the field you want from N2
Then if you want to join to other tables, put that all in brackets and give it an alias and include it in a join.
Select N1.reference, N1.OrderNoteCount, N2.notes_desc LastNote
FROM
(select reference, count(reference) OrderNoteCount, Max(notes_key) MaxNoteId
from custnote
where reference != ''
Group by reference
) N1
JOIN
(
select reference, count(reference) OrderNoteCount, notes_key, notes_desc
from custnote
where reference != ''
Group by reference, notes_key, notes_desc
) N2 ON N1.MaxNoteId = N2.notes_key
To expand on Eyvind's answer I would create a program to uses the RecNo() function to pull records within a given range, say 10,000 records.
You could then programmatically cycle through the large table in chucks of 10,000 records at a time and preform your data load into you MySQL database.
By using the RecNO() function you can be certain not to insert rows more than once, and be able to restart at a know point in the data load process. That by it's self can be very handy in the event you need to stop and restart the load process.
Depending on the number of the returned rows and if you are using .NET Framework you can offset/limit the gotten DataTable on the following way:
dataTable = dataTable.AsEnumerable().Skip(offset).Take(limit).CopyToDataTable();
Remember to add the Assembly System.Data.DataSetExtensions.