I have this table:
userid | property
1 | propA
1 | propC
2 | propA
2 | propB
And need this output for an csv export/import
userid;propA;propB;probC
1;yes;no;yes
2;yes;yes;no
Is that possible without any script language like php?
It would be totally okay for me if "yes" and "no" are just "1" and "0" (e.g.) but it is important that I need just one row for each user and one field for each property.
You can use conditional aggregation. However, your format is not CSV (hint: the "C" means comma).
To get that format, you can do:
select t.userid,
max(case when t.property = 'propA' then 'Yes' else 'No' end) as PropA,
max(case when t.property = 'propB' then 'Yes' else 'No' end) as PropB,
max(case when t.property = 'propC' then 'Yes' else 'No' end) as PropC
from table t
group by t.userid;
This happens to work because "Yes" is later in the alphabet than "No". Personally, I would just use numbers, 0 and 1:
select t.userid,
max(t.property = 'propA') as PropA,
max(t.property = 'propB') as PropB,
max(t.property = 'propC') as PropC
from table t
group by t.userid;
I want to select ALWAYS a column in my view, and set it with CASES.
example:
SELECT isDone
,doneN
from...
I have to set isDone in this way:
if done is 1 isDone is 'yes'
if done is 0 isDone is 'no'
(doneN is a column from another table, isDone instead doesn't exist in other tables, so it's a "virtual" column)
Thank you in advice
Is this what you want?
select (case when doneN = 1 then 'yes' else 'no' end) as isDoneN
. . .
You didn't specify whether 'done' will always be 0 or 1. If there are more values or you want to catch other values, use something like this:
select (case when done = 1 then 'yes'
when done = 0 then 'no'
else '' end) as isDone
, doneN
from ...
If the 'done' is constrained to be 0 or 1, you can use:
select (case when done = 1 then 'yes'
else 'np' end) as isDone
, doneN
from ...
I'm about to build some sort of function or query where I can check if a certain record already exists in the database. The following rules apply:
The table has 6 columns
My yet-to-build-query has access to a complete row-object (all 6 values)
This query should find each row with at least 4 out of 6 corresponding values from the object I passed
Using MySQL
Is it even possible to build a query like this? My goal is to have a function which can return true if it's likely that a row like the passed object is already existing in the database.
Is my only option to make a query with multiple where-statements (where I try for each combination 4 different values)?
pseudo:
function getSimilarRow(Row_Object $row)
{
//select *
//from table_x
//where 4 out of 6 properties from object $row apply
}
You could use a case statement in the where clause for each property you are trying to match. If it meets the criteria then give the case statement a value of 1; if it doesn't then give it 0. The sum of the cases should then be >= 4.
I'm not that familiar with MySQL but the following will work (I knocked up a quick SQL Fiddle to show it working):
select * from SomeTable where
(case when propertyOne = 'value1' then 1 else 0 end) +
(case when propertyTwo = 'value2' then 1 else 0 end) +
(case when propertyThree = 'value3' then 1 else 0 end) +
(case when propertyFour = 'value4' then 1 else 0 end) +
(case when propertyFive = 'value5' then 1 else 0 end) +
(case when propertySix = 'value6' then 1 else 0 end) >= 4
Obviously you could change your logic in each clause if you'd prefer them to be likes or anything. You could even apply a weighting to each column by using something other than just 1 if you needed to get really creative.
I my order by clause I want to do something like
select MyDate
from MyTable
order by case when MyDate is null then 1 else 0 end, MyDate
how can I write
order by case when MyDate is null then 1 else 0 end, MyDate
in Zend
I already tried
->order('by case when MyDate is null then 1 else 0 end', 'MyDate')
suggestions?
Following what I found on this article, MySQL Orderby a number, Nulls last, this maybe could work for you:
->order(new Zend_Db_Expr("-MyDate DESC"));
Would be nice to provide us with error message or echo $select so we could see where problem is.
Try this:
->order(new Zend_Db_Expr('case when MyDate is null then 1 else 0 end, MyDate'));
Passing Zend_Db_Expr object always puts it in query 'as it is' with no modification.
I am hoping this is a relatively simple question to answer. I have a list of transactions in a database table and I want to extract into columns an enum value (y/n) to each motorcycle manufacturer that exists in that table.
I have tried the following query:
SELECT
accCode,
rnFuncBool(accCode,'HON') purchasedHonda,
rnFuncBool(accCode,'YAM') purchasedYamaha,
rnFuncBool(accCode,'KAW') purchasedKawsaki,
rnFuncBool(accCode,'SUZ') purchasedSuzuki,
rnFuncBool(accCode,'DUC') purchasedDucati,
rnFuncBool(accCode,'KTM') purchasedKTM,
rnFuncBool(accCode,'SYM') purchasedSym,
rnFuncBool(accCode,'VIC') purchasedVictory
FROM _emarsys_vehiclessold WHERE accCode<>'' GROUP BY accCode
and the function rnFuncBool is as follows:
DELIMITER $$
USE `phcontacts`$$
DROP FUNCTION IF EXISTS `rnFuncBool`$$
CREATE DEFINER=`root`#`localhost` FUNCTION `rnFuncBool`(
fnAccCode VARCHAR(6),
fnAccMan VARCHAR(3)
) RETURNS VARCHAR(1) CHARSET utf8
BEGIN
IF (SELECT COUNT(*) FROM _emarsys_vehiclessold WHERE accCode=fnAccCode COLLATE utf8_unicode_ci AND vehichleManufacturer=fnAccMan COLLATE utf8_unicode_ci )>0 THEN
RETURN 'y';
ELSE
RETURN 'n';
END IF;
END$$
DELIMITER ;
Whilst this seems a really logical solution for a quick return the main table contains over 48,000 rows and so the execution time is in the minutes.
I did try working with a join on a temporary table but that only returned one manufacturer when grouped by the customer account code.
Of course I could try group_concat but that is not what I really want to achieve.
If anybody has any thoughts on how I can achieve this that would be brilliant.
As always many thanks in advance.
Cheers
Graham
If you go for boolean 1/0 instead of y/n then you can greatly simplify things for yourself and do a cross-tab problem query which'll be way more efficient...
SELECT
accCode,
SUM(CASE WHEN accCode ='HON' THEN 1 ELSE 0 END) purchasedHonda,
SUM(CASE WHEN accCode='YAM' THEN 1 ELSE 0 END) purchasedYamaha,
...
SUM(CASE WHEN accCode='VIC' THEN 1 ELSE 0 END) purchasedVictory
FROM _emarsys_vehiclessold WHERE accCode<>''
GROUP BY accCode
That being said, your code and what I've shown an abridged amendment to is grouping by accCode, which is what you've said you want, but I'm not sure how much value there is for you unless you're looking to construct a lookup table or something similar in which case you could simply get a list of distinct accCode and do the rest by hand or in excel just as quickly as writing sql to do it.
Whenever you get "looping" like this in a design, there is frequently a much more efficient design.
It's hard to figure out why you would need a udf, and why that queries the same table, and why that query needs to be performed 8 times for every row in the table (or, more precisely every row where accCode<>''). If 48,000 rows match the criteria in that outer query, that's going to be 384,000 calls to the function, which is going to be a total 384,001 queries executed against the database.
I just can't fathom why you would need to do that, to get the specified resultset.
It would be much more efficient to get the information in just one pass through the table, with a query something like this:
SELECT accCode
, MAX(IF(vehichleManufacturer='HON','y','n')) AS purchasedHonda
, MAX(IF(vehichleManufacturer='YAM','y','n')) AS purchasedYamaha
, MAX(IF(vehichleManufacturer='KAW','y','n')) AS purchasedKawasaki
, ...
FROM _emarsys_vehiclessold
WHERE accCode<>''
GROUP
BY accCode
Your function includes a specification that the comparison should be done case insensitive collation. If you need to specify that, it can be done in the SQL
, MAX(IF(vehichleManufacturer='HON' COLLATE utf8_unicode_ci,'y','n'))
That query is likely to benefit from a covering index on accCode and vehichleManufacturer.
(That's an odd spelling in that vehichleManufacturer column name.)
The MySQL-specific IF() function could be replaced with an equivalent ANSI CASE expression, e.g.:
, MAX(CASE WHEN vehichleManufacturer='HON' THEN 'y' ELSE 'n' END)
Try:
SELECT accCode,
case sum(CASE accCode WHEN 'HON' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedHonda,
case sum(CASE accCode WHEN 'YAM' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedYamaha,
case sum(CASE accCode WHEN 'KAW' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedKawsaki,
case sum(CASE accCode WHEN 'SUZ' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedSuzuki,
case sum(CASE accCode WHEN 'DUC' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedDucati,
case sum(CASE accCode WHEN 'KTM' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedKTM,
case sum(CASE accCode WHEN 'SYM' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedSym,
case sum(CASE accCode WHEN 'VIC' THEN 1 ELSE 0 END)
when 0 then 'n' else 'y'
end purchasedVictory
FROM _emarsys_vehiclessold WHERE accCode<>'' GROUP BY accCode
Many thanks to Steph for your help on this. To explain the data is being exported to a CSV file for external use and so the system it is being imported into needs a flat file only.
I have modified your query slightly and hey presto it works:
SELECT accCode,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='HON' THEN 1 ELSE 0 END)>0,'y','n')) purchasedHonda,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='KAW' THEN 1 ELSE 0 END)>0,'y','n')) purchasedKawasaki,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='SUZ' THEN 1 ELSE 0 END)>0,'y','n')) purchasedSuzuki,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='DUC' THEN 1 ELSE 0 END)>0,'y','n')) purchasedDucati,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='KTM' THEN 1 ELSE 0 END)>0,'y','n')) purchasedKTM,
(IF (SUM(CASE WHEN `vehichleManufacturer` ='SYM' THEN 1 ELSE 0 END)>0,'y','n')) purchasedSym,
(IF (SUM(CASE WHEN `vehichleManufacturer`='YAM' THEN 1 ELSE 0 END)>0,'y','n')) purchasedYamaha,
(IF (SUM(CASE WHEN `vehichleManufacturer`='VIC' THEN 1 ELSE 0 END)>0,'y','n')) purchasedVictory
FROM _emarsys_vehiclessold WHERE accCode<>''
GROUP BY accCode
Many thanks
Graham