sql question Select * From * where one=two order by - mysql

I need some help with a query.
i want to select from a table, some values, but the values depend on the value of an other cell. after i select i need to sort them.
Can i use ELECT column FROM table WHERE one=two ORDER BY ...?
thanks,
Sebastian

Yes you can, as long as you spell SELECT correctly.
Here is an example you can copy and paste into your MySQL Query Browser to see a query of this type in action:
CREATE TABLE table1 (
id INT NOT NULL,
name1 VARCHAR(100) NOT NULL,
name2 VARCHAR(100) NOT NULL,
sortorder INT NOT NULL
);
INSERT INTO table1 (id, name1, name2, sortorder) VALUES
(1, 'Foo', 'Foo', 4),
(2, 'Boo', 'Unknown', 2),
(3, 'Bar', 'Bar', 3),
(4, 'Baz', 'Baz', 1);
SELECT id
FROM table1
WHERE name1 = name2
ORDER BY sortorder;
Result:
4
3
1

Maybe some working examples will help:
This returns over 8100 records from one of my databases:
SELECT * FROM fax_logs WHERE fee = service_charge
This returns over 2700 records from my data:
SELECT * FROM fax_logs WHERE fee = service_charge + 5
This returns over 6900 records:
SELECT * FROM fax_logs WHERE fee = service_charge + copies

I might misunderstood your question, but I think you are trying to compare values of the first and second column. In Mysql, you can refer columns by number, not by name, only inside ORDER BY clause:
SELECT * FROM table ORDER BY 1 (order by the first column). You cannot use column index in WHERE.

Related

SQL: Can I refer/access data the current row in a window function?

Here is an example. Suppose I have the following table:
id | list
--------+----------
10 |
| 10,20
20 | 10,20
For each id value, I'd like to calculate the number of rows having a list value which contains that id value. The result would be look like that:
id | count of lists
--------+----------
10 | 2
| 0
20 | 2
I suggest a window function should be used, but it seems that I can't access the id value from within such a function.
I totally agree that it is BAD design. This question is about the possibility.
Any MySQL/PostgreSQL solution is fine.
Assuming that you are using MySQL, and assuming that your table has the name test, and assuming that both columns are string types:
SELECT
t1.id, count(t2.list)
FROM
(test t1 LEFT JOIN test t2 ON
(t2.list LIKE CONCAT('%,', t1.id, ',%')) OR
(t2.list LIKE CONCAT('%,', t1.id)) OR
(t2.list LIKE CONCAT(t1.id, ',%')))
GROUP BY t1.id;
Please be aware that this solution might be very slow depending on the number of records you have and depending on the average length of the strings in the list field.
If you need something faster, I think it couldn't be a single query. Perhaps we would have to write a stored procedure or some application logic for that, or use additional tables or columns and a series of multiple SQL statements.
Before I start, as mentioned above, this is a poor design. However, this is how I would query it:
CREATE TABLE #Lists (id int, list varchar(500));
INSERT INTO #Lists (id, list) VALUES
(10, NULL), (NULL, '10,20'), (20, '10,20');
WITH cte AS (
SELECT LEFT(list, INSTR(list, '%,%')-1) AS value, SUBSTRING(list, INSTR(list, '%,%') + 1, 500) AS list FROM #Lists
UNION ALL
SELECT CASE WHEN list LIKE ('%,%') THEN LEFT(list, INSTR(list, '%,%')-1) ELSE list END AS value, CASE WHEN list LIKE ('%,%') THEN SUBSTRING(list, INSTR(list, '%,%') + 1, 500) END AS list FROM cte
WHERE CHAR_LENGTH(list) > 0
)
SELECT value, COUNT(*) FROM cte GROUP BY value;
DROP TABLE #Lists;
This solution allows for any number of values in the list string (like '10,20,30').
Ideally, the list values should be stored in a separate table so that each record has a single value, such as CREATE TABLE BetterDesign (id int, value int) INSERT INTO BetterDesign (id, value) VALUES (10, NULL), (NULL, 10), (NULL, 20), (20, 10), (20, 20). Along with a million other reasons, this is better for querying SELECT value, COUNT(*) FROM BetterDesign GROUP BY value. That being said, I understand the pains of legacy systems.

How Can i count multple columns?

Here is my Table
I want to count reference number and per permit ex. BP, AP, OP
My Sample Query
SELECT
C.CompanyName,
A.ReferenceNumber,
Count(CR.BP,
CR.AP,
CR.SP,
CR.FP,
CR.EP,
CR.ELP,
CR.MP,
CR.EGPP,
CR.OP,
CR.EPTO,
CR.ELPTO,
CR.MPTO,
CR.FSIC,
CR.AI,
CR.EPTO_R,
CR.ELPTO_R,
CR.MPTO_R,
CR.LOA)
From Companies AS C
inner join ApplicationDetails as A on(C.CompanyId = A.CompanyID)
inner join CertificateRecords as CR on(A.ReferenceNumber = CR.ReferenceNumber)
group by A.ReferenceNumber
ERROR is The Count function requires 1 argument(s).
Count refers to rows, not columns.
There for, it makes no sense to use it on multiple columns.
You can either use a column name, an asterisk or a constant (the last 2 are equivalent).
The reason for these options is that count ignores null values - so you can use it in 2 different ways.
When using a column name, you will get the number of values in that column (per group, if you are using it with group by. Note that null is not considered a value here, so if your column is nullable, you'll get only the number of rows where it's not null.
When using asterisk or a constant, count will not ignore null values, even if all the columns in a row are contains null - that row will still get counted.
Here is a quick demo I've made to illustrate it:
DECLARE #T AS TABLE
(
col1 int NULL,
col2 int NULL
)
INSERT INTO #T VALUES
(1,1),
(1,2),
(1,3),
(1, NULL),
(2,1),
(2,2),
(2,3),
(2, NULL),
(NULL, 1),
(NULL, 2),
(NULL, 3),
(NULL, NULL)
Count with all options:
SELECT col1,
COUNT(col2) As ColumnName,
COUNT(*) Asterisk,
COUNT(1) Constant
FROM #T
GROUP BY col1
Results: (note that the column with the column name ignores the null rows)
col1 ColumnName Asterisk Constant
NULL 3 4 4
1 3 4 4
2 3 4 4
Compare count(*) with count(1):
SELECT COUNT(*) Asterisk,
COUNT(1) Constant
FROM #T
Results:
Asterisk Constant
12 12

My SQL query result issue when using aggregate and union all

I have the following query on a student enrollment table, which has the student_id, first_name, enrollment_date (DATETIME) , price (Float) as the columns,
My problem is when I run this query on MySQL I get a "BLOB" value for the price column on the first part of the query when there is a value for price and in the second section of the query as well.
I want to extract the results to a csv, and do not want "NULL" in the excel sheet, hence I have used the IFNULL condition which seems to be the reason for "BLOB" value coming on the price column.
If I don't have IFNULL on the price column I get the results with "NULL" being set for price column.
If I change the IFNULL(price,'') to IFNULL(price, 0) then also things work but I am artificially putting a '0' for price when it is null this I don't want to do ... any help ?
select
student_id AS AS `student_id`,
first_name AS `first_name`,
enrolment_date AS `enrolment_date`,
IFNULL(price, '') AS `price`,
IFNULL(price * 0.1, '') AS `gst`,
IFNULL(price * 1.1, '') AS `price_ex_gst`
from
student_enrolment
where
student_id = 123 and
month(enrolment_date) = 10
union all
select
student_id AS `student_id`,
count(1) AS `count(1)`,
'Total' AS `Total`,
sum(`price`) AS `sum(price)`,
(sum(`price`) * 0.1) AS `gst`,
(sum(`price`) * 1.1) AS `price_ex_gst`
from
student_enrolment
where
student_id = 123 and
month(enrolment_date) = 10
I think the problem are the data types. Convert the price to a string and then use ifnull():
IFNULL(format(price, 4), '') AS `price`,
IFNULL(format(price * 0.1, 4), '') AS `gst`,
IFNULL(format(price * 1.1, 4), '') AS `price_ex_gst`
As a note: I would use coalesce() instead of ifnull(), because coalesce() is the ANSI standard function for this purpose.

SQL Query to get number of entries

I am trying to select a random number of entries based on a specified parameter.
Like If I have a table T
T( id, data1, data2 ,no);
Now no is a field with a random bunch of numbers.
I want to get a random subset of T such that the number of no is at a particular value.
For example lets say I want total no=7
T(0,a,a,4);
T(1,B,B,4);
T(2,v,v,1);
T(3,d,d,2);
T(4,d,d,3);
The output of the query to the query would be either
T(0,a,a,4);
T(4,d,d,3);
OR
T(1,B,B,4);
T(2,v,v,1);
T(3,d,d,2);
etc.
Is this possible? I couldn't think of a logic. The best I could think of was retrieving them one row at a time and keep counting no but that's inefficient.
(NOTE: If the count exceeds no it is acceptable but not the other way around)
This will get you pretty close.
create table t ( name varchar(1), num tinyint ) ;
insert into t (name, num) values ( 'a', 4 ), ('b', 2), ('c', 3),
('d',1), ('e', 4), ('f', 1),('g', 6);
Here's the query:
select * from
(select name, num, #cum := #cum + num as cumulate from
(select * from t order by rand()) as t3,
(select #cum := 0 ) as t1
) as t2
where cumulate <= 7;
Here's a fiddle. Im sure it can be optimized but I was curious to see how to create it.

MySQL query: How to calculate the average of values in a row?

The AVG() function calculates column-means but how can I retrieve the mean of several values in the same row like so:
SELECT MEAN(A.a, A.b, ... , A.n) FROM A;
EDIT: sure, as cherouvim suggests I can do:
SELECT MEAN(A.a + A.b + ... + A.n) / n FROM A;
but I'm trying to find out if there's a leaner way.
select (A.a + A.b) / 2 from A;
I stumbled upon a similar situation. This came useful: http://tech-blog.borychowski.com/index.php/2009/02/mysql/average-value-in-a-row/
From the page:
When we do:
SELECT *, (V.rank_0 + V.rank_1 + V.rank_2) / 3
AS row_avg FROM voting V
we only receive correct averages for the rows where all values are not NULL. But when I have e.g. 3, NULL, 4 I’d like to get 3.5 as a return. That’s the moment when function COALESCE() comes handy.
What does COALESCE () do? From MySQL manual we have:
Returns the first non-NULL value in the list, or NULL if there are no non-NULL values.
mysql> SELECT COALESCE(NULL,1);
-> 1
mysql> SELECT COALESCE(NULL,NULL,NULL);
-> NULL
And these information will help us to build another SELECT statement:
SELECT *,
#first part
(COALESCE(V.rank_0, 0)
+ COALESCE(V.rank_1, 0)
+ COALESCE(V.rank_2, 0))
/
#second part
(3 -
(COALESCE(V.rank_0 - V.rank_0, 1)
+ COALESCE(V.rank_1 - V.rank_1, 1)
+ COALESCE(V.rank_2 - V.rank_2, 1))
) AS row_avg FROM voting V
If no one else finds a better solution, you could always just add them together, then divide by the number of columns you added.
Not pretty, but it works.
Not specifically MySql, but the idea should be easy enough to translate over.
CREATE TABLE A (id int identity(1,1), C1 int, C2 int, C3 int)
GO
INSERT INTO A VALUES (1,1,1)
INSERT INTO A VALUES (2,2,2)
INSERT INTO A VALUES (3,3,3)
INSERT INTO A VALUES (1,2,3)
INSERT INTO A VALUES (4,5,6)
GO
CREATE VIEW A_Values
AS
SELECT ID, AVG(Val) AS Average
FROM
(
SELECT ID, C1 AS Val FROM A
UNION ALL
SELECT ID, C2 AS Val FROM A
UNION ALL
SELECT ID, C3 AS Val FROM A
) Q
GROUP BY ID
GO
SELECT * FROM A_Values
GO
I'm not familiar with the MySQL syntax, but what about dumping the row data into a temporary table as multiple rows with a single column, and then using the AVG() function to obtain your result?