Select Left(columnA,2) or right(columnA,1) - mysql

Is there a way in MySql to use an either or in a select column. For instance
select left(columnA,2) or right(columnA,1) as columnAlias, sum(columnB)
from table
where ((left(columnA,2) in ('aa','bb','cc')) or (right(columnA,1) in ('a,','b','c')))
group by columnAlias
what I have is a table where either the first 2 characters of the column or the last character of the column indicates the facility. I need to sum the values by facility. A union gets me part way there then I could loop through the resulting dataset and sum things up in the code (or do a stored proc to return the sums), but I am wondering if there is a way to just get it from the query.
I've tried using the union query as an on the fly temp table and doing the select and group on that but if there are no records returned from either of the select statments then it throws a "column columnA cannot be null error.
Also tried with the syntax above, but not getting the results I am expecting. Any other ways to do this through the query?

using a CASE would prob be your best bet here.
http://dev.mysql.com/doc/refman/5.0/en/case-statement.html

Related

SELECT no rows and no columns?

Is it possible to write a SELECT statement, which returns dataset with zero rows and zero columns?
A dataset will always have at least 1 column, even if it contains no data.
SELECT NULL;
EDIT:
As pointed out by #eggyal , above syntax will return a null row.
His query select null from dual where false; wont return a row.
Not possible in my opinion. You will get at least one column, but no rows.
Select null from yourTable where 1 = 2;
This works for postgresql:
create table test22 ();
select * from test22;
it's normally used for Creating empty Table from an Existing Table
CREATE TABLE NEW_TABLE_NAME AS
SELECT *
FROM EXISTING_TABLE_NAME
where 1=2
No, but it is possible to return a query with no rows. In order to do this without referencing any tables, you can use a subquery:
SELECT NULL FROM (SELECT NULL) AS temp WHERE false;
This query will have one (empty) column, but no rows.
I've used the above construct when there is a query that is different in different cases, followed by a code loop that iterates through the results, and under some conditions you want to make it skip the loop. Replacing the query with the one above is a way of returning empty results and thus skipping the loop without an if block. Because the query contains no table names, that aspect of the code never needs to be changed, and for this reason I prefer it to adding a condition like WHERE false in an existing query.
I prefer this solution to the more concise one referencing dual because that construct is not supported in PostgreSQL; this solution works with any backend that supports subqueries.

(SQL) Union combination with additional data

I use a database program called Agility by WiSys at my job. I had an unusual occurrence where part the data I needed was found in one column of a specific table and the rest was in another column in another table.
I used a UNION to combine these tables, but I have found that I cannot add any more data needed for the rest of my report. When I do, I receive a Error Message stating: All queries combined using a UNION, INTERSECT OR EXCEPT operator must have an equal number of expressions in their target lists.
Basically, the UNION works as needed, I have combined my data into one column, however, I cannot call any additional data needed in the query because the UNION prevents that data from being called.
Here is my query without the additional data I need:
SELECT table1_sql.UnionColumn1,
FROM table1_sql
UNION
SELECT table2_sql.UnionColumn2 AS CombinedColumn
FROM table2_sql
ORDER BY CombinedColumn
I need to have the UNION with these extra columns in my report as well:
SELECT table1_sql.UnionColumn1,
table1_sql.ExtraColumn1,
table1_sql.ExtraColumn2,
table1_sql.ExtraColumn3,
table1_sql.ExtraColumn4
FROM table1_sql
UNION
SELECT table2_sql.UnionColumn2 AS CombinedColumn
FROM table2_sql
ORDER BY CombinedColumn
An example of the data that I am trying to retrieve would be:
Example Data Where Order_No is the data that I want to join via UNION and everything else is data that is also needed but not allowed with a UNION.
The program Agility is not as robust as other programs, so I am somewhat limited in my ability to complete this reports using alternatives to UNION. Please advice.
The error message is telling you the complete story. When using a union BOTH queries MUST have the same number of columns. You can work with it by simply adding some hard coded NULLS.
SELECT table1_sql.UnionColumn1,
table1_sql.ExtraColumn1,
table1_sql.ExtraColumn2,
table1_sql.ExtraColumn3,
table1_sql.ExtraColumn4
FROM table1_sql
UNION
SELECT table2_sql.UnionColumn2 AS CombinedColumn
, NULL
, NULL
, NULL
, NULL
FROM table2_sql
ORDER BY CombinedColumn
Please note you will have to order by UnionColumn1 because the column names in the second query are not the name of the columns in the final result set. Only the names from the first query.

Union query to combine results of 3 tables

I am relatively new to coding so please have patience.
I am trying to combine data from 3 tables. I have managed to get some data back but it isn't what i need. Please see my example below.
select oid, rrnhs, idnam, idfnam, dte1, ta
as 'access type' from person
left join
(select fk_oid, min(dte), dte1, ta
from
((Select fk_oid,min(accessdate) as dte, accessdate1 as dte1, accesstype as ta
from vascularpdaccess
where isnull(accesstype)=false group by fk_oid)
union
(Select fk_oid, min(hpdate) as dte, hpdate as dte1, HPACCE as ta
from hdtreatment
where isnull(hptype)=false group by fk_oid)) as bla
group by fk_oid) as access
on person.oid=access.fk_oid
where person.rrnhs in (1000010000, 2000020000, 3000030000)
My understanding with a union is that the columns have to be of the same data type but i have two problems. The first is that accesstype and hpacce combine in to a the same column as expected, but i dont want to actually see the hpacce data (dont know if this is even possible).
Secondly, the idea of the query is to pull back a patients 'accesstype' date at the first date of hpdate.
I dont know if this even makes sens to you guys but hoping someone can help..y'all are usually pretty nifty!
Thanks in advance!
Mikey
All queries need to have the same number of columns in the SELECT statement. It looks like you first query has the max number of columns, so you will need to "pad" the other to have the same number of columns. You can use NULL as col to create the column with all null values.
To answer the question (I think) you were asking... for a UNION or UNION ALL set operation, you are correct: the number of columns and the datatypes of the columns returned must match.
But it is possible to return a literal as an expression in the SELECT list. For example, if you don't want to return the value of HPACCE column, you can replace that with a literal or a NULL. (If that column is character datatype (we can't tell from the information provided in the question), you could use (for example) a literal empty string '' AS ta in place of HPACCE AS ta.
SELECT fk_oid
, MIN(HPDATE) AS dte
, hpdate AS dte1
, NULL AS ta
-- -------------------- ^^^^
FROM hdtreatment
Some other notes:
The predicate ISNULL(foo)=FALSE can be more simply expressed as foo IS NOT NULL.
The UNION set operator will remove duplicate rows. If that's not necessary, you could use a UNION ALL set operator.
The subsequent GROUP BY fk_oid operation on the inline view bla is going to collapse rows; but it's indeterminate which row the values from dte1 and ta will be from. (i.e. there is no guarantee those values will be from the row that had the "minimum" value of dte.) Other databases will throw an exception/error with this statement, along the lines of "non-aggregate in SELECT list not in GROUP BY". But this is allowed (without error or warning) by a MySQL specific extension to GROUP BY behavior. (We can get MySQL to behave like other databases and throw an error of we specify a value for sql_mode that includes ONLY_FULL_GROUP_BY (?).)
The predicate on the outer query doesn't get pushed down into the inline view bla. The view bla is going to materialized for every fk_oid, and that could be a performance issue on large sets.
Also, qualifying all column references would make the statement easier to read. And, that will also insulate the statement from throwing an "ambiguous column" error in the future, when a column named (e.g.) ta or dte1 is added to the person table.

MySQL Error Message: Subquery Returns More than 1 Row

Would you help me to fix this, please:
SELECT
(SELECT AES_DECRYPT(cryptoword, SHA2('DatabaseEncryption1', 512)) FROM file_tree) AS cryptoword1,
(SELECT AES_DECRYPT(name, SHA2(cryptoword1, 512)) FROM file_tree) AS name;
As the topic says, I get error saying that my subquery returns more than 1 row. What I look for to achieve is:
Get the cryptoword for the particular database record.
Use that cryptoword to decrypt the rest of the record.
Repeat the process for all the table records/multiple records satisfying WHERE condition, which I can add later
My query works, if I use the query for one record only. However, I need to get multiple records within from the table. Every record has its own cryptoword, which is different per each row. My task is therefore to get the cryptoword for particular record, and to use that one to decrypt the rest of the record. I need to repeat this process for all the table records.
Because of performance reasons, it all needs to be formatted within one query.
Thank you in advance.
Work out the value of cryptoword1 in a sub-query, then you can reuse the result to work out the value of name in the outer query.
SELECT
cryptoword1,
AES_DECRYPT(name, SHA2(cryptoword1, 512)) AS name
FROM
(
SELECT
AES_DECRYPT(cryptoword, SHA2('DatabaseEncryption1', 512)) AS cryptoword1,
name
FROM
file_tree
)
AS sub_query
Subqueries in the select statement must evaluate to a single value, or else you will get this error. This makes sense since you are looking to fill the value for one field.

MySql Duplicated rows string comparation performance

I have a table with more then 2 million records,
I need to find duplication records in column with string type additionaly I have index for this field.
I have next query:
select m.* from member as m
where lower(m.username) in
(select lower(b.username) from member as b
where b.Username like 'a%'
group by b.username
having count(b.username) >= 2);
sub-query return only 4 records less then 0.2 seconds, but if I use them in where conditions section, this query working very long time and never return results....
I have tried to run next query, that theoretically the same logic:
select * from member as m where lower(Username) in (lower('a1'),
lower('a2'),lower('a3'),lower('a4'));
and it works fine and fast.
what is the issues ?
additionally I would like to run query with out where b.Username like 'a%' part?
In common case MySQL can not use index for IN subqueries
This is sad, but, actually, MySQL can not recognize "constant subqueries". What does it mean? It means that if you have a subquery that returns static list of values - and you use that in IN within another query, MySQL will not use index (by range).
Why it is so?
Actually, the most correct point is - because MySQL treats following queries:
.. WHERE `field` IN ('foo', 'bar', 'baz')
and
.. WHERE `field` IN (SELECT `col` FROM t)
-as different queries (I'm assuming that column col in table t in second query have same values, i.e. 'foo', 'bar', 'baz'). First query is equivalent for it's "expected" case, i.e. for range of values. But second query is equal for = ANY subquery - and so MySQL will not use index for that.
What to do
Actually, your case and cases similar to it - are cases when it's better to split your query into two parts. First part will be retrieve static list of values from your table. Second part will substitute result of your first part into IN clause and then you'll get index using.
Alternative - you can use JOIN syntax for table to itself. That may seems useful if you want to resolve an issue with one query (or if your list is too long)