MySQL Join table on calculated value - mysql

I am not sure if this is possible but here goes.
I am using MySQL and need to complete a statement that produces an output as follows.
I have a table which contains a completeddate field and an enquirydate field.
I need to get data on the time difference between theses fields for which I have the following code
SELECT DATE (completedate) - DATE (enqdate) AS `timediff`, COUNT(*) AS TotalCount
FROM cia_enquiry
WHERE (DATEDIFF(CURDATE(), enqdate) < 30) AND completedate > 1
GROUP BY `timediff`
ORDER BY `timediff` ASC
The above code simply outputs a figure of days between the dates and the total count of entires within the last 30 days (and not counting those entries that are not complete)
I now need to reference the "timediff" results against another table and pull another field from that table.
For example if timediff = 1, then we need to find the id of 1 in another table and return the description field from this table.
Ultimately we should end up with something similar to
timediff TotalCount description
0 52 Within 24 hrs
1 13 24-48hrs
etc etc .........

It can be done; you have two choices
Create a temporary table with the result of your query and then join this table with your second table
Use your first query as a subquery and join it with your second table
Option 1
create temporary table temp_tbl
select
...
;
# Important: create the indexes you need
alter table temp_tbl
add index index1(field1), ... ;
# Now join your second table
select a.*, b.*
from temp_tbl as a join tbl2 as b on ...;
Option 2
select a.*, b.*
from (
select ... # here is your query
) as a join tbl2 as b on ...
Hope this helps you

The date calculation will give you a bunch of decimal points worth of values...
you should use ROUND()
or look up CEIL and FLOOR functions.

Related

How I can make a new column with subtraction for two raws with +1 shift

I have two columns
sum1 sum2
100 70
60 20
30 10
I need one more column col3 which can be calculate by subtraction like this
sum1 sum2 col3
100 70 null
60 20 -80
30 10 -50
-80 I can get by 20-100 and -50 by 10-60. I need to make subtraction of raws with shift on one
How can I get this new column by sql query?
In relational databases, the records are by default unordered, so there is no inherent concept of previsous record. For what you request to be possible, you do need a column in the original table that can be used to order the records. I assume that such column exists in the table and is called id.
If you are running MySQL 8.0, this is straightforward using window function LAG(), which gives you access to the previous record:
SELECT sum1, sum2, sum2 - LAG(sum1) OVER(ORDER BY id) col3
FROM mytable
If you are running an older MySQL version, then it is a bit more complicated. A common solution is to self-join the table, and to use a NOT EXISTS condition to locate the previous record (this phrases as : recover the record has a smaller id than the current record, and for which no other record exists with an id smaller than the current record and greater than the joined record):
SELECT t.sum1, t.sum2, t.sum2 - t_last.sum1 col3
FROM mytable t
LEFT JOIN mytable t_last
ON t_last.id < t.id
AND NOT EXISTS (
SELECT 1
FROM mytable t1
WHERE t1.id < t.id AND t1.id > t_last.id
)
Create a procedure that will accept 2 int parameters . Inside it write the substraction statement. Now since we cannot call this procedure in select statement we will make a wrapper class function that will call the procedure and then call this function by select statements and insert into 3rd column. We cannot directly call the function/procedure because we cannot perform DML operation in select statement while calling a function

Mysql return multiple rows, only need 1

How can I get just one result from multiple in MySQL?
SELECT DATE_ADD(data, INTERVAL(-WEEKDAY(data)) DAY) AS D
FROM Done
GROUP BY D
It gives me "2017-08-07" and "2017-08-14" and I need them both, but one at the start and the other at the end. How can I do this?
The result from the query is called result set in terms of database.
So, your result set contains 2 rows, or in other words you can say that there are 2 results in the result set from this query.
In fact you have them separate - each on its own row in the result set.
When fetching the result in the programming language you are using, you will receive them as a collection or array.
Then, you can get the first and the second element of that collection/array and print them as desired.
Try This :-
DROP TABLE IF EXISTS tbl_1;
CREATE TEMPORARY TABLE tbl_1
AS
SELECT
DATE_ADD(data, INTERVAL(-WEEKDAY(data)) DAY) AS D,#row_num:=#row_num+1 as row_id
FROM
Done,(select #row_num:=0)rownum
GROUP BY D;
DROP TABLE IF EXISTS tbl_2;
CREATE TEMPORARY TABLE tbl_2
AS
SELECT * from tbl_1;
SELECT tbl_2.D,tbl_1.D from tbl_1
JOIN tbl_2 ON tbl_1.row_id=tbl_2.row_id+1

Sort by multiple duplicate rows, then delete

I have a query that I have been working on in phpmyadmin that sorts entries based on a duplicate geometric locations,
The Query looks like this:
SELECT *, COUNT(*) c
FROM `spatial_locations`
WHERE 1
GROUP BY x,y,z HAVING c > 1
ORDER BY `c` DESC
And it returns a proper result ordered by 'c'
What I would like to do is further expand upon this query to go through the results, and delete any entries where C > 10 ordered by date (basically make any entries to the system older than the most recent 10 go away)
Is this possible the way I am suggesting it or am I on the completely wrong track?
delete any entries where C > 10 .... with that do you to perform a DELETE operation (OR) just exclude those records from your SELECT resultset. If you just want to remove from select query resultset then you can probably just modify your HAVING condition saying
HAVING c <= 10
Well, to DELETE you can have those rows inserted in a TEMPORARY table and use that table instead like
CREATE TEMPORARY TABLE test AS
SELECT some_unique_id_column, COUNT(*) c
FROM `spatial_locations`
WHERE 1
GROUP BY x,y,z
HAVING c <= 10
ORDER BY `c` DESC
Then perform the DELETE operation like
DELETE FROM `spatial_locations`
WHERE some_unique_id_column IN (
SELECT some_unique_id_column FROM test);

GROUP BY each 6 months in one record

I am having trouble retrieving certain data from a db through a SELECT query as such:
SELECT table.something
FROM table
WHERE table.date BETWEEN 'from' AND 'to'
GROUP BY (each 6 months between the from and to date).
Any idea how this can be done without having to recur to a view and an external grouping through code.
Something like this will work:
SELECT
table.something,
CEIL(MONTH(date)/6) as monthVALUE
FROM
table
WHERE
table.date BETWEEN 'from' AND 'to'
GROUP BY
monthVALUE
Instead of worrying about on a single query create a temporary table insert record with the start date and end date and your some other column. and use the select query for each record to get the results and store it in the temporary table and select the temporary table.

Fast MAX, GROUP BY on the concatenation of mulliple columns

I have a table with 4 columns: name, date, version,and value. There's an composite index on all four, in that order. It has 20M rows: 2.000 names, approx 1.000 dates per name, approx 10 versions per date.
I'm trying to get a list that give for all names the highest date, the highest version on that date, and the associated value.
When I do
SELECT name,
MAX(date)
FROM table
GROUP BY name
I get good performance and the database uses the composite index
However, when I join the table to this in order to get the MAX(version) per name the query takes ages. There must be a way to get the result in about the same magnitude of time as the SELECT statement above? I can easily be done by using the index.
Try this: (I know it needs a few syntax tweaks for MySQL... ask for them and I will find them)
INSERT INTO #TempTable
SELECT name, MAX(Date) as Date
FROM table
Group By name
select table.name, table.date, max(table.version) as version
from table
inner join #TempTable on table.name = #temptable.name and table.date = #temptable.date
group by table.name, table.date