MySQL implementation of an iterator - sql

is it a way to implement an iterator in mysql which could return a column as
"1/10"
"2/10"
...
"10/10"
Lets say the form is a/b, as input we have only b. Is it possible to solve this without procedure?
EDIT
An example. We have a relation PRINTS (id, work_id, edition_no) and EDITIONS (id, work_id, size, edition_size). For web-interface I am trying to render a select with possible options for prints. Html-options should look like
<option value="1">1/10</option>
<option value="2">2/10</option>
All my select list I render with SQL from database, but in this case I do not see any possibility to get it from database in way I need it. Sql should return 2 columns with option-value and option-text. That is a question.

SQL is all about relations, that is, tables. The natural way would be to create a one-column table with 10 (or however much you want) consecutive numbers, index it by that column, and select enough numbers from there, using order by and limit.

Use the CONCAT function to concatenate strings in MySQL:
SELECT CONCAT('<option value="', p.edition_no, '">', p.edition_no. '/', e.edition_size, '</option>')
FROM PRINTS p
JOIN EDITIONS e ON e.work_id = p.work_id

Related

SqlQuery and SqlFieldsQuery

it looks that SqlQuery only supports sql that starts with select *? Doesn't it support other sql that only select some columns like
select id, name from person and maps the columns to the corresponding POJO?
If I use SqlFieldQuery to run sql, the result is a QueryCursor of List(each List contains one record of the result). But if the sql starts with select *, the this list's contents would be different with field query like:
select id,name,age from person
For the select *, each List is constructed with 3 parts:
the first elment is the key of the cache
the second element is the pojo object that contains the data
the tailing element are the values for each column.
Why was it so designed? If I don't know what the sql that SqlFieldsQuery runs , then I need additional effort to figure out what the List contains.
SqlQuery returns key and value objects, while SqlFieldsQuery allows to select specific fields. Which one to use depends on your use case.
Currently select * indeed includes predefined _key and _val fields, and this will be improved in the future. However, generally it's a good practice to list fields you want to fetch when running SQL queries (this is true for any SQL database, not only Ignite). This way your code will be protected from unexpected behavior in case schema is changed, for example.

SQL - just view the description for explanation

I would like to ask if it is possible to do this:
For example the search string is '009' -> (consider the digits as string)
is it possible to have a query that will return any occurrences of this on the database not considering the order.
for this example it will return
'009'
'090'
'900'
given these exists on the database. thanks!!!!
Use the Like operator.
For Example :-
SELECT Marks FROM Report WHERE Marks LIKE '%009%' OR '%090%' OR '%900%'
Split the string into individual characters, select all rows containing the first character and put them in a temporary table, then select all rows from the temporary table that contain the second character and put these in a temporary table, then select all rows from that temporary table that contain the third character.
Of course, there are probably many ways to optimize this, but I see no reason why it would not be possible to make a query like that work.
It can not be achieved in a straight forward way as there is no sort() function for a particular value like there is lower(), upper() functions.
But there is some workarounds like -
Suppose you are running query for COL A, maintain another column SORTED_A where from application level you keep the sorted value of COL A
Then when you execute query - sort the searchToken and run select query with matching sorted searchToken with the SORTED_A column

One select for multiple records by composite key

Such a query as in the title would look like this I guess:
select * from table t where (t.k1='apple' and t.k2='pie') or (t.k1='strawberry' and t.k2='shortcake')
... --10000 more key pairs here
This looks quite verbose to me. Any better alternatives? (Currently using SQLite, might use MYSQL/Oracle.)
You can use for example this on Oracle, i assume that if you use regular concatenate() instead of Oracle's || on other DB, it would work too (as it is simply just a string comparison with the IN list). Note that such query might have suboptimal execution plan.
SELECT *
FROM
TABLE t
WHERE
t.k1||','||t.k2 IN ('apple,pie',
'strawberry,shortcake' );
But if you have your value list stored in other table, Oracle supports also the format below.
SELECT *
FROM
TABLE t
WHERE (t.k1,t.k2) IN ( SELECT x.k1, x.k2 FROM x );
Don't be afraid of verbose syntax. Concatenation tricks can easily mess up the selectivity estimates or even prevent the database from using indexes.
Here is another syntax that may or may not work in your database.
select *
from table t
where (k1, k2) in(
('apple', 'pie')
,('strawberry', 'shortcake')
,('banana', 'split')
,('raspberry', 'vodka')
,('melon', 'shot')
);
A final comment is that if you find yourself wanting to submit 1000 values as filters you should most likely look for a different approach all together :)
select * from table t
where (t.k1+':'+t.k2)
in ('strawberry:shortcake','apple:pie','banana:split','etc:etc')
This will work in most of the cases as it concatenate and finds in as one column
off-course you need to choose a proper separator which will never come in the value of k1 and k2.
for e.g. if k1 and k2 are of type int you can take any character as separator
SELECT * FROM tableName t
WHERE t.k1=( CASE WHEN t.k2=VALUE THEN someValue
WHEN t.k2=otherVALUE THEN someotherValue END)
- SQL FIDDLE

Is it possible in SQL to return a first row that has attribute names and then values

I am wondering if there is a way to write the SQL so that it would return me a result as usual but now, on the first row that would return also the attribute names.
To explain what I mean:
say you have a table "test" which has 2 attributes "id" and "name":
id name
1 nik
2 tst
query:
SELECT * FROM test;
produces:
1 nik
2 tst
but what I want it to return is this:
id name
1 nik
2 tst
Is this possible?
edit: I am using PostreSQL
You cannot return the names and the actual column values in a single result unless you give up on the real datatypes (which is probably not what you want).
Your example mixes character data and numeric data in the id column and Postgres will (rightfully) refuse to return such a result set.
Edit:
I tested the "union" solution given e.g. by JNK and it fails (as expected) on Postgres, Oracle and SQL Server precisely because of the non-matching datatypes. MySQL follows it's usual habits of not throwing errors and simply converts everything to characters.
Extremely generic answer since you don't provide an RDBMS:
SELECT id, name FROM(
SELECT 'id' as 'id', 'name' as 'name', 1 as 'Rank'
UNION ALL
SELECT *, 2 as 'Rank' FROM test) as X
ORDER BY [RANK]
EDIT
Thanks to Martin for pointing out the need for the ORDER BY
Assuming you are on SQL Server, you can get the column names of a specific table by using this query:
select column_name 'Column Name', data_type 'Data Type'
from information_schema.columns
where table_name = 'putYourTableNameHere'
Then, you'll have to UNION your things together.
I agree with OMG Ponies above, the way to get this meta-data is usually from the interface you use.
for example the Perl DBI module has a method fetchrow_hashref where the columns of the returned row are returned as an associative array (hash) where the colnames are the keys.
print $ref->{'name'}; # would print nik or tst
Update:
I had forgotten to add that some of these interface layers have a method that return s the col names and you could use that instead of adding the names into your result set.
The DBI method you'd use would be $sth->{NAMES}->[0] would return the first column name.
Depending on your tools / technique, but here are a couple:
If you're using SSMS (Sql-Server), and want to copy/paste your results with the column headers:
Query Window -->
R-Click
Results -->
Grid or Text -->
Check-mark the 'Include column headers in the result set' option
If you're using Sql-Server, you can query meta-tables (sys.columns, etc.)
If you're using an ASP.NET databound control, you usually have access to methods or properties (sqldatareader.getname(i), etc.)
Anyway -- just depends on the layer you're trying to get the names from -- if these above don't help, then edit / re-tag your question so we can focus on whatever tool you're wanting to use to do this.
EDIT for PostgresSQL
If you're using PostgresSQL, you can query meta-tables (information_schema.columns, etc.)

What kind of SQL clause is this? Any way to convert it to SQL?

what kind of SQL is this?
SELECT IFNULL(SUM(prenotazione.VALUTAZIONE),0) AS somma,
COUNT(*) AS numero
FROM `prenotazione`
WHERE prenotazione.USER_ID=18793 AND
prenotazione.PRENOTAZIONE_STATO_ID IN (10,11)
I'm using propel as my ORM.
Any way to convert that kind of SQL to Mysql SQL?
This query is valid in MySQL. It selects all rows from the prenotazione table where the user_id is 18793 and the prenotazione_stato_id is 10 or 11. The resulting rows are summarized: in the numero column you get the number of rows found, in the somma column you get the sum of the valutazione values. If no rows were selected, SUM() would return NULL. To prevent this, IFNULL([expr1],[expr2]) is applied, which returns [expr1] if it is not null, and [expr2] if it is null. This makes sure you always return a number.
There is no easy way to do this with Propel, since your result cannot be easily mapped to a Propel object. The best thing you can do is use the underlying database layer (PDO) to escape your parameters and handle the resultset, and you don't open an extra database connection or something like that.
When considering portability, Standard SQL is your friend. This query can be very easily transformed into Standard SQL-92:
Terminate the statement with a semi-colon.
Replace IFNULL with COALESCE.
Remove the single quotes from the table name.
With better spacing it could look like this:
SELECT COALESCE(SUM(prenotazione.VALUTAZIONE), 0) AS somma,
COUNT(*) AS numero
FROM prenotazione
WHERE prenotazione.USER_ID = 18793
AND prenotazione.PRENOTAZIONE_STATO_ID IN (10,11);
That said, for MySQL you probably would need to undo step 3... which leads me to suspect it was MySQL syntax in the first place.
Using Babelfish to give a rough translation from Italian to English results in
SELECT IFNULL(SUM(reservation.APPRAISAL),0) AS sum,
COUNT(*) AS number
FROM `reservation`
WHERE reservation.USER_ID=18793 AND
reservation.RESERVATION_STATE_ID IN (10,11)
Share and enjoy.