What is '-' in front of a column in mysql mean? - mysql

What is the significance of "-" (Last line of the code, before a.emp_no) in the following code? I have been trying to understand but I want sure answers. Please Help!!!!!!!!!!!!!!!!!!
SELECT *
FROM
(SELECT
e.emp_no,
e.first_name,
e.last_name,
NULL AS dept_no,
NULL AS from_date
FROM
employees.employees e
WHERE
last_name = 'Denis'
UNION SELECT
NULL AS emp_no,
NULL AS first_name,
NULL AS last_name,
dm.dept_no,
dm.from_date
FROM
employees.dept_manager dm) as a
ORDER BY -a.emp_no DESC;

if emp_no is a number - then it is asking to order by the negative of the number. you could also say
order by a.emp_no

Related

MySQL multipe subqueries result in very slow response

I have two tables contacts and calllist. contacts has multiple columns containing phone numbers. calllist has only one column from_number containing phone numbers. I'm trying to get all phone numbers from the column from_number which do not match the phone numbers in the table calllist.
Here is my working but probably very inefficient and slow SQL query:
SELECT from_number AS phone_number, COUNT(from_number) AS number_of_calls
FROM calllist
WHERE from_number NOT IN (
SELECT businessPhone1
FROM contacts
WHERE businessPhone1 IS NOT NULL
)
AND from_number NOT IN (
SELECT businessPhone2
FROM contacts
WHERE businessPhone2 IS NOT NULL
)
AND from_number NOT IN (
SELECT homePhone1
FROM contacts
WHERE homePhone1 IS NOT NULL
)
AND from_number NOT IN (
SELECT homePhone2
FROM contacts
WHERE homePhone2 IS NOT NULL
)
AND from_number NOT IN (
SELECT mobilePhone
FROM contacts
WHERE mobilePhone IS NOT NULL
)
AND (received_at BETWEEN '$startDate' AND DATE_ADD('$endDate', INTERVAL 1 DAY))
GROUP BY phone_number
ORDER BY number_of_calls DESC
LIMIT 10
How do i rewrite this SQL query to be faster? Any help would be much appreciated.
try this
SELECT from_number AS phone_number, COUNT(from_number) AS number_of_calls
FROM calllist
WHERE from_number NOT IN (
SELECT businessPhone1
FROM contacts
WHERE businessPhone1 IS NOT NULL
UNION
SELECT businessPhone2
FROM contacts
WHERE businessPhone2 IS NOT NULL
UNION
SELECT homePhone1
FROM contacts
WHERE homePhone1 IS NOT NULL
UNION
SELECT homePhone2
FROM contacts
WHERE homePhone2 IS NOT NULL
UNION
SELECT mobilePhone
FROM contacts
WHERE mobilePhone IS NOT NULL
)
AND (received_at BETWEEN '$startDate' AND DATE_ADD('$endDate', INTERVAL 1 DAY))
GROUP BY phone_number
ORDER BY number_of_calls DESC
LIMIT 10
I don't like the schema design. You have multiple columns holding 'identical' data -- namely phone numbers. What if technology advances and you need a 6th phone number??
Instead, have a separate table of phone numbers, with linkage (id) to JOIN back to calllist. That gets rid of all the slow NOT IN ( SELECT... ), avoids a messy UNION ALL, etc.
If you desire, the new table could have a 3rd column that says which type of phone it is.
ENUM('unknown', 'company', 'home', 'mobile')
The simplified query goes something like
SELECT cl.from_number AS phone_number,
COUNT(*) AS number_of_calls
FROM calllist AS cl
LEFT JOIN phonenums AS pn ON cl.id = pn.user_id
WHERE cl.received_at >= '$startDate' AND
AND cl.received_at < '$endDate' + INTERVAL 1 DAY
AND pn.number IS NULL -- not found in phonenums
GROUP BY phone_number
ORDER BY number_of_calls DESC
LIMIT 10

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, , >= or when the subquery is used as an expr

SELECT
INT_ID, FST_NAME, LAST_NAME, MID_NAME, FIRST_NAME,LAST_NAME, MIDDLE_NAME, Null, Null,
CASE WHEN LEVELS = 'Done' THEN 1 ELSE NULL END AS Verified,
NULL
FROM Customer_Table
WHERE
CREATEDDATE = (SELECT DISTINCT MAX(CREATEDDATE) FROM Customer_Table GROUP BY INT_ID)
I got the following error message from sql server.
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Obviously, this subquery can return more than one value:
where CREATEDDATE = (Select Distinct max(CREATEDDATE) From Customer_Table group by INT_ID )
I am pretty sure you intend a correlated subquery instead:
select . . .
from Customer_Table ct
where ct.createddate = (select max(ct2.createddate)
from Customer_Table ct2
where ct2.int_id = ct.int_id
);
This sounds like you want a max per group query:
SELECT
c1.INT_ID,
c1.FST_NAME,
c1.LAST_NAME,
c1.MID_NAME,
c1.FIRST_NAME,
c1.LAST_NAME,
c1.MIDDLE_NAME,
NULL,
NULL,
CASE WHEN c1.LEVELS = 'Done' THEN 1 END AS Verified,
NULL
FROM Customer_Table c1
INNER JOIN
(
SELECT INT_ID, MAX(CREATEDDATE) AS max_date
FROM Customer_Table
GROUP BY INT_ID
) c2
ON c1.INT_ID = c2.INT_ID AND
c1.CREATEDDATE = c2.max_date;
There is a nicer (and possibly more performant) way of doing this using ROW_NUMBER, but your version of MySQL may not support it.

Invalid use of group by while showing username with heighest salary in group

I use MySQL
I wanted to show some records like Total Salary per designation , avg salary etc. All are working except : I want to show person name with heighest salary in group. When I use the query as below , I give error : Invalid use of group function . I ran it many times using different tweaks , ordering of query , still giving error. What may be the issue here ?
SELECT designation , SUM(salary) as salary_as_per_designation ,
count(*) as num_employees ,
avg(salary) as avg_salary ,
MIN(salary) as min_salary_of_emp_per_designation,
MAX(salary) as max_salary_of_emp_per_designation ,
(SELECT name FROM articles where salary = max(salary) GROUP BY designation LIMIT 1) as emp_name_min_sal
FROM articles GROUP BY designation;
The weired thing is when i use on 2nd last line above like .... where salary = 10000... 100 as Some random value query works but gives wrong result , I mean wrong name for the user with heighest salary in group.
My table structure is as follows :
CREATE TABLE IF NOT EXISTS `articles` (
`id` int(12) NOT NULL,
`name` varchar(256) NOT NULL,
`salary` double NOT NULL,
`designation` enum('tech_support','developer','tester','designer') NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;
Thanks.
SELECT ilv.*,
(SELECT GROUP_CONCAT(name)
FROM articles
where salary = ilv.max_salary_of_emp_per_designation
) as emp_name_min_sal
FROM
(
SELECT designation , SUM(salary) as salary_as_per_designation ,
count(*) as num_employees ,
avg(salary) as avg_salary ,
MIN(salary) as min_salary_of_emp_per_designation,
MAX(salary) as max_salary_of_emp_per_designation
FROM articles
GROUP BY designation
) AS ilv
Does this work? Note sub-select conditions, you're looking for salaries within the designation grouping?
SELECT designation,
SUM(salary) as salary_as_per_designation,
count(*) as num_employees,
avg(salary) as avg_salary,
MIN(salary) as min_salary_of_emp_per_designation,
MAX(salary) as max_salary_of_emp_per_designation,
(SELECT max(name)
FROM articles
where designation = a1.designation
and salary = (select max(salary) from articles
where designation = a1.designation)) as emp_name_min_sal
FROM articles a1
GROUP BY designation;
Use this query instead,
SELECT MAX(salary) into #max_sal FROM articles;
SELECT designation , SUM(salary) as salary_as_per_designation ,
count(*) as num_employees ,
avg(salary) as avg_salary ,
MIN(salary) as min_salary_of_emp_per_designation,
MAX(salary) as max_salary_of_emp_per_designation ,
(SELECT name FROM articles where salary = #max_sal GROUP BY designation LIMIT 1) as emp_name_min_sal
FROM articles GROUP BY designation;
Hope this will work, thank you.

SQL Plus Error At Line 1

I need to list each order, list the order ID, order date, customer ID, customer first name, customer last name, sales rep ID, sales rep first name, and sales rep last name; sort by order ID; Format the order date as “mm/dd/yy”.
Here is my UPDATED Code!
SELECT Order_ID as Order_ID, to_char(Order_Date, 'mm/dd/yyyy') as Date, OR.Cust_ID as Cust_ID,
Cust_FName as Cust_FName, Cust_LName as Cust_LName, SR.Sales_Rep_ID as Sales_Rep_ID,
Sales_Rep_FName as Sales_Rep_FName, Sales_Rep_LName as SalesRepLName
FROM ORDER_arb OR, CUSTOMER_arb C, SALES_REP_arb SR
WHERE OR.Cust_ID = C.Cust_ID AND
C.Sales_Rep_ID = SR.Sales_Rep_ID
ORDER BY Order_ID;
I am receiving this error:
UPDATE!!
Error at Line 1: FROM keyword not found where expected
I would appreciate any input.
Thanks
Try this. Please change 'OR' to 'ORD' and 'as Date' to 'as OrderDate'.
Because DATE is a keyword in oracle. and OR alias seems working different than wen think. If you still needs to use column alias sa Date, please use with double quotes as "Date"
SELECT ORD.Order_ID as Order_ID, to_char(ORD.Order_Date, 'mm/dd/yyyy') as OrderDate, ORD.Cust_ID as Cust_ID,
C.Cust_FName as Cust_FName, C.Cust_LName as Cust_LName, SR.Sales_Rep_ID as Sales_Rep_ID,
SR.Sales_Rep_FName as Sales_Rep_FName, SR.Sales_Rep_LName as SalesRepLName
FROM ORDER_arb ORD, CUSTOMER_arb C, SALES_REP_arb SR
WHERE ORD.Cust_ID = C.Cust_ID
AND C.Sales_Rep_ID = SR.Sales_Rep_ID
ORDER BY Order_ID;

mysql group and sort a UNION

In my guestbook I have 2 tables: messages and replies.
Now, I want to get all messages grouped by id (means that message and corresponding replies will be grouped/together) and sorted by date DESC (the newest messages will be first; if a message is the oldest one, but the corresponding reply is the newest of all messages, this group will be on the top of the table), while replies will be sorted by date ASC (oldest reply on the top).
Here my mysql query that works good except it doesnt sort replies by date ASC
SELECT msg.id as id, msg.comment, msg.date_added as date_added, 0 as is_reply
FROM messages AS msg
UNION
SELECT reply.msg_id as id, reply.comment, reply.date_added as date_added, 1 as is_reply
FROM pg_reply as reply
GROUP BY id
ORDER BY date_added DESC, is_reply ASC
is_reply ASC doesnt do the job as I supposed
reply.msg_id specifies id of reply's parent (messages.id)
What the result should look like>
- message A
- oldest reply B
- old reply C
- new reply Z // this is the newest message in the guestbook
- newer message E // is newer than A but older than the newest message in the guestbook, which is Z
- reply F // (this reply is newer than all messages but message Z)
For this answer I'm going to assume that reply.msg_id is a linkfield to the original message.
SELECT id, comment, date_added, is_reply FROM (
SELECT
msg.id as id
, msg.comment
, msg.date_added as date_added
, 0 as is_reply
FROM messages AS msg
UNION
SELECT
reply.msg_id as id
, reply.comment
, reply.date_added as date_added
, 1 as is_reply
FROM pg_reply as reply ) AS allmsg
ORDER BY id DESC, is_reply, date_added DESC
This works assuming that msg_id is an autoincrement field and that newer id's also have a newer date_added timestamp.
Remarks on the original code
In your original code you have
GROUP BY id
ORDER BY date_added DESC, is_reply ASC
The GROUP BY implicitly orders on id ASC; the following ORDER BY overrides that and orders by date_added first and is_reply second.
However if date_added is a datetime then the chance of two post having the same time are remote (esp. for replies, it takes time to write them),
so the 2nd order clause hardly ever gets used.
GROUP BY should only be used if you have an aggregate function in your select, such as SUM or COUNT
If you want to remove duplicates from your select do not use group by, use distinct as in select distinct a,b,c from table1 where ...
similar solution:
SELECT sort, project, reviewdate, reviewby, subject, venue, filename, remarks1, remarks2, url
FROM (
SELECT '1' AS sort, project, last_updated AS reviewdate, reviewby, concat( project, '(',
TYPE , '): ', subject ) AS subject, venue, filename, remarks1, remarks2, concat( project, '/',
TYPE , '/', filename ) AS url
FROM `upload_cmg`
WHERE (
(
subject LIKE '%prt%'
OR project LIKE '%prt%'
OR TYPE LIKE '%prt%'
)
AND (
subject LIKE '%mouda%'
OR project LIKE '%mouda%'
OR TYPE LIKE '%mouda%'
)
)
UNION SELECT '2' AS sort, project, last_updated AS reviewdate, reviewby, concat( project, '(',
TYPE , '): ', subject ) AS subject, venue, filename, remarks1, remarks2, concat( project, '/',
TYPE , '/', filename ) AS url
FROM `upload_cmg`
WHERE subject LIKE '%mouda%'
GROUP BY url
) AS vin
ORDER BY sort, reviewdate DESC
I would recommend adding a message parent field in both and sorting on that as your primary sort, with date then being the sort after that.. otherwise you will have replies showing up mixed up with other messages that were posted between replies. You can have the message parent of a non-reply message be itself.
Try this:
SELECT id, comment, date_added, is_reply
FROM (
SELECT msg.id as id, msg.comment, msg.date_added as date_added, 0 as is_reply
FROM messages AS msg
INNER JOIN pg_reply as reply
ON reply.msg_id = msg.id
GROUP BY msg.id, msg.comment, msg.date_added, 0 as is_reply
ORDER BY CASE WHEN MAX(reply.date_added) > msg.date_added THEN MAX(reply.date_added) ELSE msg.date_added END DESC
UNION
SELECT reply.msg_id as id, reply.comment, reply.date_added as date_added, 1 as is_reply
FROM pg_reply as reply
ORDER BY date_added ASC ) a
ORDER BY id