Thursday, 28 May 2015

MySQL EXTRACT() Function

The EXTRACT() function is used to return a single part of a date/time, such as year, month, day, hour, minute, etc.

Syntax

EXTRACT(unit FROM date)
Where date is a valid date expression and unit can be one of the following:
Unit Value
MICROSECOND
SECOND
MINUTE
HOUR
DAY
WEEK
MONTH
QUARTER
YEAR
SECOND_MICROSECOND
MINUTE_MICROSECOND
MINUTE_SECOND
HOUR_MICROSECOND
HOUR_SECOND
HOUR_MINUTE
DAY_MICROSECOND
DAY_SECOND
DAY_MINUTE
DAY_HOUR
YEAR_MONTH

MySQL Date Functions

The following table lists the most important built-in date functions in MySQL:
FunctionDescription
NOW()Returns the current date and time
CURDATE()Returns the current date
CURTIME()Returns the current time
DATE()Extracts the date part of a date or date/time expression
EXTRACT()Returns a single part of a date/time
DATE_ADD()Adds a specified time interval to a date
DATE_SUB()Subtracts a specified time interval from a date
DATEDIFF()Returns the number of days between two dates
DATE_FORMAT()Displays date/time data in different formats

Wednesday, 27 May 2015

Mysql: Select where field has more than 2 non duplicated records sql



This should be pretty easy but I am just not able to figure this one out.
Got a table with customers order information. There is a field within this table called customers_email_address and customers_id along with a number of other non-essential fields. I need to locate distinct records where the entries in the customers_email_address field are different but unique to the same customers_id. In other words, I need to find out what customers have changed their email address in their account since their account's inception so I can update my email advertising program with their new email address. Something I didn't think of when the site was designed!
Maybe an example would be:
customers_ID    customers_email_address
1               joeschome@hotmail.com
2               frankj@hotmail.com
1               joeschome@hotmail.com
2               frankj@hotmail.com
1               joeschome@yahoo.com
2               frankj@yahoo.com
3               janefr@live.com
3               janefr@live.com
3               janefr@live.com

result of query should look like this:

customers_id    customers_email_address
1               joeschome@hotmail.com
1               joeschome@yahoo.com
2               frankj@hotmail.com
2               frankj@yahoo.com



Solution:
CREATE TABLE orders (`customers_ID` int, `customers_email_address` varchar(21));
   
INSERT INTO orders
    (`customers_ID`, `customers_email_address`)
VALUES
    (1, 'joeschome@hotmail.com'),
    (2, 'frankj@hotmail.com'),
    (1, 'joeschome@hotmail.com'),
    (2, 'frankj@hotmail.com'),
    (1, 'joeschome@yahoo.com'),
    (2, 'frankj@yahoo.com'),
    (3, 'janefr@live.com'),
    (3, 'janefr@live.com'),
    (3, 'janefr@live.com');


SELECT DISTINCT o.customers_id, o.customers_email_address
  FROM orders o JOIN
(
  SELECT customers_id
    FROM orders
   GROUP BY customers_id
  HAVING COUNT(DISTINCT customers_email_address) > 1
) q
    ON o.customers_id = q.customers_id
ORDER BY o.customers_id

MYSQL - SELECT from multiple rows, same user, different values

Below is my table called fittest. I need to find which students based on student id (studid) have taken the pre and post test as designated in the prepost column. So based on the simple table below I would need to return studid 123456. How do I write the SELECT query for this?


SELECT studid, prepost FROM `fittest` LIMIT 0, 30 ; 

    studid  prepost
    123456  pre
    123456  post
    1031460 pre
 
Solution:
 
CREATE TABLE fittest (`studid` int, `prepost` varchar(4));
 
INSERT INTO fittest(`studid`, `prepost`) 
VALUES (123456, 'pre'),(123456, 'post'),(1031460, 'pre');  


SELECT studid
  FROM fittest
 GROUP BY studid
HAVING COUNT(DISTINCT prepost) = 2
;

SELECT studid
  FROM fittest
 GROUP BY studid
HAVING (MAX(prepost = 'pre' ) +
        MAX(prepost = 'post')) = 2
   AND COUNT(DISTINCT prepost) = 2;

Output
studid
123456

Mysql: Select last 2 elements ascending followed by 1st element

I want to select the last two elements in ascending order followed by the first element.

E.g. for 20 products now I'm getting
20, 19, 1 (ordered by id).
I'm trying to get 19, 20, 1.

Solution:
CREATE TABLE Table1
    (`id` int);
   
INSERT INTO Table1    (`id`) VALUES    (1),    (2),    (3),    (4),    (5),    (6),    (7),    (8),    (9),    (10),    (11),    (12),    (13),    (14),    (15),    (16),    (17),    (18),    (19),    (20);

SELECT id
  FROM
(
  (
    SELECT id, 0 sort_order
      FROM Table1
     ORDER BY id DESC
     LIMIT 2
  )
  UNION ALL
  (
    SELECT id, 1 sort_order
      FROM Table1
     ORDER BY id 
     LIMIT 1
  )
) q
 ORDER BY sort_order, id
Output:
| ID |
|----|
| 19 |
| 20 |
|  1 |
 

Mysql cross table join

2 mysql table as follow:
items
id item_name user_id
1    test1     1    
2    test2     1
3    test3     1
4    test4     1  
project
id user_id items
1    1       1,3
2    1       2,4
how can write a join query that can return each items in a project?
project1 =>
    item1=>
      [id1] =>
      [name1] =>
    item3=>
      [id3] =>
      [name3] =>






enter image description here

First of all don't store strings of delimited values in your db. You're limiting your self with the means to normally maintain and query data. Normalize your data (in this case by introducing project_items table with project_id and item_id columns). It'll pay off big time in a long run.
In the mean time you can use FIND_IN_SET() to join your tables
SELECT p.id project_id, p.user_id, i.id item_id, i.item_name 
   FROM project p LEFT JOIN items i
     ON FIND_IN_SET(i.id, p.items) > 0
    AND p.user_id = i.user_id
 ORDER BY p.id, i.id
Output:
| PROJECT_ID | USER_ID | ITEM_ID | ITEM_NAME |
----------------------------------------------
|          1 |       1 |       1 |     test1 |
|          1 |       1 |       3 |     test3 |
|          2 |       1 |       2 |     test2 |
|          2 |       1 |       4 |     test4 |
 
 
 
UPDATE: Values of items should not contain spaces. Either remove them or use REPLACE() like this
ON FIND_IN_SET(i.id, REPLACE(p.items, ' ', '')) > 0
 

Mysql: Split (explode) comma delimited column values to rows

Description
Following is Table Structure:
eligibility_table
ID     COURSE_ID     BRANCH_IDS
1      501           621,622,623
1      502
1      503           625
2      501           621
2      505           650
3      500
Now, I am making new table structure as describe below and inserting course_table,branch_table through eligibility_table. So following, final output I want
course_table
ID COURSE_ID
1  501
1  502
1  503
2  501
2  505
3  500
branch_table
ID BRANCH_ID
1  621
1  622
1  623
1  625
2  621
2  650
 
 
Solution: 


INSERT INTO branch_table (id, branch_id)
SELECT e.id, SUBSTRING_INDEX(SUBSTRING_INDEX(e.branch_ids, ',', n.n), ',', -1) branch_id
  FROM eligibility_table e CROSS JOIN 
(
   SELECT a.N + b.N * 10 + 1 n
     FROM 
    (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
    ORDER BY n
) n
 WHERE n.n <= 1 + (LENGTH(e.branch_ids) - LENGTH(REPLACE(e.branch_ids, ',', '')))
 ORDER BY id, branch_id
 
  • The subquery with an alias of n generates on the fly a sequence of numbers (numbers or tally table) from 1 to 100 in this particular case using UNION ALL and CROSS JOIN. Sometimes it's handy to have a real tally table in your db.
  • In outer select innermost SUBSTRING_INDEX() gets everything up to n'th element in a list and outer SUBSTRING_INDEX() extract right most part after a last delimiter effectively getting n-th element itself.
  • CROSS JOIN allows us to produce a set of rows which is a cartesian product (of 100 rows in n and all rows in eligibility_table)
  • condition in WHERE clause filters out all unnecessary rows from the resultset
Note: this query will split up to 100 branch ids. If you need more or less you can adjust a limit by editing the inner subquery
Result in branch_table:
| ID | BRANCH_ID |
------------------
| 1 | 621 |
 | 1 | 622 |
 | 1 | 623 |
 | 1 | 625 |
 | 2 | 621 |
 | 2 | 650 |
 
 
 
  

MySQL update single table with join

I have a values in table "REVIEW" that need to change REVIEW_STATUS from "UNDER_REVIEW" to "Abstain" based upon other records in the table that have the same REFERENCE_NUMBER , A specific REVIEW_TYPE and that REVIEW_STATUS is "ABSTAIN".

Solution:
It was the word TABLE
UPDATE  REVIEW AS REV1  
LEFT JOIN REVIEW AS REV2 
ON (REV1.REFERENCE_NUMBER=REV2.REFERENCE_NUMBER)
SET REV1.REVIEW_STATUS='ABSTAIN' 
WHERE 
REV1.REVIEW_TYPE ='QOC' 
AND 
REV1.REVIEW_STATUS='UNDER_REVIEW'
AND 
REV2.REVIEW_TYPE ='MED_NEC'
AND (REV2.REVIEW_STATUS ='ABSTAIN' ); 

Mysql: Return row count from second table using one query

I have the following two tables. I need to select all the lightboxes from lightboxes_tbl where author ='scott@co.com'. That's obviously the easy part. Where I am stuck is that I also want to select in the same query the number of assets in each lightbox. For example, 'aircraft-types' lightbox (id = 100 / lightbox_id = 100) would return 2 assets. The 'maintenance' lightbox (id = 101 / lightbox_id = 101) would return 1 asset.
Thanks!
lightboxes_tbl
+-----+----------------+---------------+---------------------+
|id   |lightbox_name   |author         |authoried_viewers    |
+-----+----------------+---------------+---------------------+
|100  | aircraft-types |scott@co.com   |jon@co.com,aj@co.com |
+-----+----------------+---------------+---------------------+
|101  | maintenance    |scott@co.com   |nicole@co.com        |
+-----+----------------+---------------+---------------------+


lightbox_assets_tbl
+-----+-------------+-------------+---------------+----------+
|id   |lightbox_id  |asset_name   |asset_path     | asset_id |
+-----+-------------+-------------+---------------+----------+
|1    |100          |a321.jpg     |project1/imgs/ | 3700     |
+-----+-------------+-------------+---------------+----------+
|2    |100          |b757.jpg     |project1/imgs/ | 3444     |
+-----+-------------+-------------+---------------+----------+
|3    |101          |engine.jpg   |project4/imgs/ | 1444     |
+-----+-------------+-------------+---------------+----------+
 
Solution:
Make use of LEFT JOIN and COUNT()
SELECT l.*, COUNT(a.lightbox_id) total_assets FROM lightboxes_tbl l LEFT JOIN lightbox_assets_tbl a ON l.id = a.lightbox_id WHERE l.author = 'scott@co.com' GROUP BY l.id Output:
| ID | LIGHTBOX_NAME | AUTHOR | AUTHORIED_VIEWERS | TOTAL_ASSETS | |-----|----------------|--------------|----------------------|--------------|
 | 100 | aircraft-types | scott@co.com | jon@co.com,aj@co.com | 2 | 
| 101 | maintenance | scott@co.com | nicole@co.com | 1 |
 

PHP: Things to Remember While Developing a Website

These days website is an essential marketing platform for your business and key part of your marketing mix. If you are planning to have one for your own business then you can hire any web developer or you can do it on your own.

Developing a website is not the hard part, hard part is, it must serve the purpose for which you have created it. If you are able to answer the following questions then you get the winning website. Otherwise follow the blog, it will take you through the steps you may have missed during your website development.

Is your website serving the purpose you have created it for?

Is sufficient traffic coming to your website?

Does your website has any errors?

How is it performing on web?

So here are few things which you always keep in mind when developing a website:

1. Code website keeping in mind SEO: It will help your site to boost in search ranking when you make it live. For more details about SEO practices.

2. Register your Website with Google Analytics and webmaster tools: Google analytics and webmaster tools will help you to keep track of your website. Using these tools you can see daily hits of your website, categories hits based on many other filters such as city, browser etc. These tools will also tell you the words for which your website is coming in search, search rank of website and how you can improve your website search rank. The best part of these tools is that they are free:) (upto limit).

3. Don’t forget to include customized 404 error page: This is often overlooked and underestimated. However, designed carefully, these pages can make a random visitor stay on your website, take a look around and eventually find the information he or she was looking for in the first place. Effective 404 error pages communicate why a particular page couldn’t be displayed and what users can do next. A search box and list of useful resources (possibly related to the missing page) could be helpful in this case. So go and designed one for your website.

4. Create robot.txt for your website : robot.txt is a text file, which must be present in your website folder. It prevents crawlers accessing all parts(URLS) of your website and you can tell crawler about your sitemap.xml(explained later).

5. Create and submit sitemap.xml to webmaster tool: Site maps can improve search engine optimization of a site by making sure that all the pages can be found. It also tells crawler about your sitemap.xml using robot.txt file.

6. Check Your website performance: Before making a website live, you must check its performance(load speed and other errors). For this you can use google pagespeed tool.

So these are some points which can help you achieve the purpose for which you are creating your website.

It may possible that I have missed some other important points, which you are welcome to mention in comments.

Mysql: Difference between datetime and timestamp in mysql

It's important to note that datetime has a range of 1000-9999, but the range for timestamp is only 1970-2038. this can be a problem if your system has to store birthdates, or you have to handle something like the payment plan for a 30-year mortgage.


In version 5.6.5, it is possible to set a default value on a datetime column, and even make a column that will update when the row is updated. The type definition:

CREATE TABLE foo (
    creation_time     DATETIME DEFAULT CURRENT_TIMESTAMP,
    modification_time DATETIME ON UPDATE CURRENT_TIMESTAMP
)
 
 
 

In MYSQL 5 and above, TIMESTAMP values are converted from the current time zone to UTC for storage, and converted back from UTC to the current time zone for retrieval. (This occurs only for the TIMESTAMP data type, and not for other types such as DATETIME.)
By default, the current time zone for each connection is the server's time. The time zone can be set on a per-connection basis.


The DATETIME type is used when you need values that contain both date and time information. MySQL retrieves and displays DATETIME values in 'YYYY-MM-DD HH:MM:SS' format. The supported range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59'.

The TIMESTAMP data type has a range of '1970-01-01 00:00:01' UTC to '2038-01-09 03:14:07' UTC. It has varying properties, depending on the MySQL version and the SQL mode the server is running in.

You're quite likely to hit the lower limit on TIMESTAMPs in general use -- e.g. storing birthdate.

1. TIMESTAMP is 4 bytes Vs 8 bytes for DATETIME.2. Timestamps are also lighter on the database and indexed faster.
3. DATETIME is constant while TIMESTAMP is effected by the time_zone setting.

A timestamp field is a special case of the datetime field. You can create timestamp columns to have special properties; it can be set to update itself on either create and/or update.
In "bigger" database terms, tiemstamp has a couple of special-case triggers on it.

Not sure if this has been mentioned already, but worth noting in MySQL you can use something along the lines of below when creating your table columns
on update CURRENT_TIMESTAMP
This will update the time each instance you modify a row, sometimes very helpful for stored last edit info. This only works with timestamp, not datetime however.

TIMESTAMP is always in UTC (i.e. elapsed seconds since 1970-01-01, in UTC), and your mySQL server auto-converts it to the date/time for the server timezone. In the long-term, TIMESTAMP is the way to go b/c you know your temporal data will always be in UTC. E.G. you won't screw your dates up if you migrate to a different server or if you change the timezone settings on your server.
 
I recommend using neither a DATETIME or a TIMESTAMP field. If you want to represent a specific day as a whole (like a birthday), then use a DATE type, but if you're being more specific than that, you're probably interested in recording an actual moment as opposed to a unit of time (day,week,month,year). Instead of using a DATETIME or TIMESTAMP, use a BIGINT, and simply store the number of milliseconds since the epoch (System.currentTimeMillis() if you're using Java). This has several advantages:
  1. You avoid vendor lock-in. Pretty much every database supports integers in the relatively similar fashion. Suppose you want to move to another database. Do you want to worry about the differences between MySQL's DATETIME values and how Oracle defines them? Even among different versions of MySQL, TIMESTAMPS have a different level of precision. It was only just recently that MySQL supported milliseconds in the timestamps.
  2. No timezone issues. There's been some insightful comments on here on what happens with timezones with the different data types. But is this common knowledge, and will your co-workers all take the time to learn it? On the other hand, it's pretty hard to mess up changing a BigINT into a java.util.Date. Using a BIGINT causes a lot of issues with timezones to fall by the wayside.
  3. No worries about ranges or precision. You don't have to worry about what being cut short by future date ranges (TIMEZONE only goes to 2038).
  4. Third-party tool integration. By using an integer, it's trivial for 3rd party tools (e.g. EclipseLink) to interface with the database. Not every third-party tool is going to have the same understanding of a "datetime" as MySQL does. Want to try and figure out in Hibernate whether you should use a java.sql.TimeStamp or java.util.Date object if you're using these custom data types? Using your base data types make's use with 3rd-party tools trivial.
This issue is closely related how you should store a money value (i.e. $1.99) in a database. Should you use a Decimal, or the database's Money type, or worst of all a Double? All 3 of these options are terrible, for many of the same reasons listed above. The solution is to store the value of money in cents using BIGINT, and then convert cents to dollars when you display the value to the user. The database's job is to store data, and NOT to intrepret that data. All these fancy data-types you see in databases(especially Oracle) add little, and start you down the road to vendor lock-in.

The major difference is
  • a INDEX's on Timestamp - works
  • a INDEX's on Datetime - Does not work
Timestamp data type stores date and time but in UTC format, not in current zone format as datetime do. And when you fetch data, timestamp again convert that into current zone time. So suppose you are in USA and getting data from server which has time zone of USA, then you will get the date and time according to USA time zone. Timestamp data type column always get updated automatically when its row gets updated. So it can be useful to track when a particular row was updated last time.

Beware of timestamp changing when you do a UPDATE statement on a table. If you have a table with columns 'Name' (varchar), 'Age' (int), and 'Date_Added' (timestamp) and you run the following DML statement
UPDATE table
SET age = 30
then every single value in your 'Date_Added' column would be changed to the current timestamp.


I have always ignored timestamp data type while designing a database instead used datetime data type whenever I had to store date and time. Recently I read, what exactly timestamp data type is for and I think it is worth sharing.
 So I’ll begin with the reason, why I never used timestamp!
My perception was that both data types (timestamp and datetime) store date and time in database and are same.
Now, why I am saying that we must also consider timestamp is because of following reasons:
  1. Timestamp data type stores date and time but in UTC format, not in current zone format as datetime do. And when you fetch data, timestamp again convert that into current zone time. So suppose you are in USA and getting data from server which has time zone of USA, then you will get the date and time according to USA time zone.
  2. Timestamp data type column always get updated automatically when its row gets updated. So it can be useful to track when a particular row was updated last time.
These are the two main reasons I am aware of (apart from range and storage) and it is worth considering timestamp data type while designing the database.

From my experiences If you want a date field in which insertion happens only once and u don't want to have any update or any other action on that particular field go with date time .
For example in a user table REGISTRATION DATE field. In that user table if u want to know the last logged in time of a particular user go with a field of timestamp type so that field get updated.
If you are creating the table from PHPMyAdmin default setting will update the timestamp field when row update happens. If your timestamp filed is not updating with row updation .

 

mysql query To get the top two salary from each department

**Department table name** 
**following with fields name**

 id , empid ,salary ,departid ,status

how to get the top two highest salaries from each department with single query in mysql
Try
SELECT id, empid, salary, departid, status
  FROM 
(
  SELECT id, empid, salary, departid, status, 
         @n := IF(@g = departid, @n + 1, 1) rownum,
         @g := departid
    FROM table1
   ORDER BY departid, salary DESC 
) q
 WHERE q.rownum <= 2

What it does it generates in inner select a rank for each employee in each department based on the salary. Then in outer select it filters out all rows that have rank more than 2 (top two).

Mysql: How to select rows with multiple specific column values in single query?

Table A
itemNo   colorNo
1        3
1        4
2        4
2        70
3        9
3        10
 
Try

SELECT *
  FROM A
 WHERE (itemNo = '1' AND colorNo =  '4')
    OR (itemNo = '2' AND colorNo = '70')
    OR (itemNo = '3' AND colorNo =  '9')

or you can also do this
SELECT * FROM A WHERE (itemNo, colorNo) IN ((1, 4),(2, 70),(3, 9)) Output:
| ITEMNO | COLORNO |
--------------------
| 1 | 4 |
| 2 | 70 |
| 3 | 9 |
 

Mysql: converting comma separated values into rows in mysql

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t.values, ',', n.n), ',', -1) value
  FROM table1 t CROSS JOIN 
(
   SELECT a.N + b.N * 10 + 1 n
     FROM 
    (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
    ORDER BY n
) n
 WHERE n.n <= 1 + (LENGTH(t.values) - LENGTH(REPLACE(t.values, ',', '')))
 ORDER BY value