Select most recent from mysql table - mysql

I have two mysql tables:
Item containing items that one can buy:
CREATE TABLE `item` (
`itemid` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`itemid`)
) ENGINE=InnoDB;
Purchase containing all purchases:
CREATE TABLE `purchase` (
`purchaseid` int(11) NOT NULL AUTO_INCREMENT,
`date` date DEFAULT NULL,
`amount` int(11) DEFAULT NULL,
`itemid` int(11) DEFAULT NULL,
PRIMARY KEY (`purchaseid`)
) ENGINE=InnoDB;
I want to select the most 20 recent purchases based on date and purchaseid and join the item table to show the name of these purchases. If an item has been purchased more than once in the 20 recent purchases it should only show up once. No duplicates. I really can't figure this out.. Maybe you can? Thanks!

Wouldn't it be:
SELECT `name`
from `item` join `purchase` using(`itemid`)
group by `itemid` order by `date` desc limit 20
OR
SELECT DISTINCT `name`
from `item` join `purchase` using(`itemid`)
order by `date` desc limit 20
Using DISTINCT allows you to omit duplicates, as does GROUP BY (which also allows you to perform functions on the grouped data)

Related

I'm trying to display total no. of orders by each vendor every year?

I'm trying to display total no. of orders by each vendor every year?
Table: Sales
Table: Products
Table: Vendors & Vendor_Info
select year(orderdate) as date_year,count(orderid) as count, OrderID
from products
NATURAL JOIN sales
NATURAL JOIN vendor_info
WHERE products.Vendor_Id=vendor_info.Vendor_Id
group by year(orderdate);
on doing this query i'm getting
query result
Where am i going wrong ? and what would the most efficient way to do this?
-- Table structure for table `products`
--
CREATE TABLE IF NOT EXISTS `products` (
`Product_id` varchar(255) NOT NULL,
`OrderId` int(11) NOT NULL,
`Manufacture_Date` date DEFAULT NULL,
`Raw_Material` varchar(255) DEFAULT NULL,
`Vendor_Id` int(11) DEFAULT NULL,
PRIMARY KEY (`Product_id`),
KEY `OrderId` (`OrderId`)
);
-- Table structure for table `sales`
--
CREATE TABLE IF NOT EXISTS `sales` (
`OrderID` int(11) NOT NULL AUTO_INCREMENT,
`OrderDate` date DEFAULT NULL,
`OrderPrice` int(11) DEFAULT NULL,
`OrderQuantity` int(11) DEFAULT NULL,
`CustomerName` varchar(255) DEFAULT NULL,
PRIMARY KEY (`OrderID`)
) AUTO_INCREMENT=10 ;
-- Table structure for table `Vendors`
--
CREATE TABLE IF NOT EXISTS `Vendors` (
`Raw_material` varchar(255) DEFAULT NULL,
`Vendors` varchar(255) DEFAULT NULL,
`Vendor_id` int(11) DEFAULT NULL,
KEY `Vendor_id` (`Vendor_id`)
)
-- Table structure for table `Vendor_info`
--
CREATE TABLE IF NOT EXISTS `Vendor_info` (
`Vendor_id` int(11) DEFAULT NULL,
`Vendor_name` varchar(255) DEFAULT NULL,
KEY `Vendor_id` (`Vendor_id`)
)
Some guesswork here, because you have not explained your requirement.
I guess you want to summarize numbers of orders by year. You can do that with a simpler query than your example, because all the data you need is in your sales table.
select year(orderdate) as date_year, count(orderid) as count
from sales
group by year(orderdate);
If this does not meet your need, please edit your question to give us more details.
If you want to get the number or orders by vendor and year yoy can use a query like this one:
select vendor_info.vendor_name,year(sales.orderdate),count(distinct products.orderId)
from vendor_info
join products on vendor_info.vendor_id=productos.vendor_id
join sales on products.orderid=sales.orderid
group by vendor_info.vendor_name,year(sales.orderdate)
Where you make a join from vendors to products and sales. Here you will get only the vendors who have sales.

How to delete all rows in a group except the newest one?

Say, I have a table similar to this:
CREATE TABLE `mytable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`application_id` int(11) NOT NULL,
`company_name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
I want to make application_id unique, but there're some duplicates in the table already. How can I group by application_id and remove all records per group, leaving just the one with the highest id?
delete from mytable
where id not in
(
select max(id)
from mytable
group by application_id
)

How can I query for rows with latest date and do an inner join on a second table?

All the examples I've seen show how to do an inner join using an alias to get rows with the latest date. I can do that with my data but I also want to do an inner join on another table and can't figure how to do both with the same query.
Here are the two tables:
CREATE TABLE `titles` (
`titleID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`titlename` tinytext NOT NULL,
`url` varchar(255) DEFAULT '',
`category` int(2) unsigned NOT NULL,
`postdate` date NOT NULL,
PRIMARY KEY (`titleID`),
KEY `category` (`category`),
CONSTRAINT `titles_ibfk_1` FOREIGN KEY (`category`) REFERENCES `categories` (`catid`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
CREATE TABLE `stats` (
`statid` int(11) unsigned NOT NULL AUTO_INCREMENT,
`score` decimal(3,2) DEFAULT NULL,
`views` int(11) unsigned DEFAULT NULL,
`favs` int(11) DEFAULT NULL,
`comments` int(11) DEFAULT NULL,
`updatedate` date NOT NULL,
`title` int(11) unsigned NOT NULL,
PRIMARY KEY (`statid`),
KEY `title` (`title`),
CONSTRAINT `stats_ibfk_1` FOREIGN KEY (`title`) REFERENCES `titles` (`titleID`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1;
My goals:
1) I want a query that gives me all the latest stats for each title.
2) I want to see the text name of the title (from the titles table).
I can use this query to get the latest score for each title.
select t.score, t.views, t.favs, t.comments, t.updatedate, t.title
from stats t
inner join (
select title, max(updatedate) as updatedate
from stats
GROUP BY title
) tm on t.title = tm.title and t.updatedate = tm.updatedate
But the problem with this query is that it displays the title column from stats which is an int. I want the text name of the title.
I can do this to get the title name and the score, but then I'm not getting the row with the latest date.
select titlename, score, updatedate
from stats
inner join titles
on titleid = title
How can I write a query that achieves both my goals?
You need to join the title table in this case as
select
s1.score,
s1.views,
s1.favs,
s1.comments,
s1.updatedate,
t.titlename
from titles t
join stats s1 on s1.title = t.titleID
join (
select title, max(updatedate) as updatedate
from stats
GROUP BY title
) s2 on s2.title = s1.title and s1.updatedate = s2.updatedate

View help. Pulling data from 3 tables

Okay, I need some major help with this subject. This is what I need the view to do. It needs to take Sum of the DKP_Change Column in the Attendance table
SELECT SUM(a.DKP_Change) FROM Attendance AS a GROUP BY Name
add the value of the initial DKP from the characters table
SELECT b.Inital_DKP FROM Characters AS b GROUP BY Name
Subtract the sum of the raid drops tabe cost
SELECT SUM(c.Cost) FROM Raid_Drops AS c GROUP BY Name
I'm entirely new to the idea of VIEWS and i'm not sure where to begin with, the name of the view should be DKP, the columns should be Name and Total_DKP, where total dkp is calculated from teh above select statements.
Here are the creates for all 3 tables.
CREATE TABLE `Attendance` (
`Date` date NOT NULL,
`Name` varchar(20) NOT NULL,
`Hours` int(11) NOT NULL,
`Penalty` float NOT NULL,
`Rank` set('Raider','Core','Elite') NOT NULL,
`Rate` int(11) NOT NULL,
`DKP_Change` float NOT NULL,
`RecordNumber` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`RecordNumber`)
) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=latin1
CREATE TABLE `Characters` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(25) NOT NULL,
`Class` varchar(25) NOT NULL,
`Spec` varchar(25) NOT NULL,
`Position` set('Healer','Tank','DPS') NOT NULL COMMENT 'Healer, Tank, or DPS',
`Usable` set('Cloth','Mail','Plate') NOT NULL COMMENT 'Type of Usable Armor? Cloth, Mail, Or Plate',
`Primary Stat` set('Agility','Strength','Intellect','Healer','Tank') NOT NULL COMMENT 'Used for Sorting Only(ie dps trinket with agility strength dps not eligible)',
`Initial_DKP` int(11) NOT NULL COMMENT 'DKP given at the start of current tier.',
`Total_DKP` int(11) NOT NULL COMMENT 'Huge Complicated Mess.',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
CREATE TABLE `Raid_Drops` (
`Record Number` int(11) NOT NULL,
`Date` date NOT NULL,
`Name of Item` varchar(25) NOT NULL,
`Item Slot` enum('Main Hand','Off Hand','Head','Neck','Shoulder','Back','Chest','Wrist','Hands','Waist','Legs','Feet','Ring 1','Ring 2','Trinket 1','Trinket 2') NOT NULL,
`Player_Name` varchar(25) NOT NULL,
`Cost` float NOT NULL,
PRIMARY KEY (`Record Number`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
You could
Join the three tables in a subselect, grouping on Name
Perform your calculations on the results of each subselect
The only part that's not entirely clear to me is if the names in Characters are unique or not. If they are, you can drop the group by. If they are not, the AVG might give you unexpected results.
SQL Statement
SELECT sumA
, initialB
, sumC
, sumA + initialB - sumC
, a.Name
FROM (
SELECT Name, SUM(DKP_Change) AS sumA
FROM Attendance
GROUP BY Name
) AS a
INNER JOIN (
SELECT Name, Inital_DKP AS initialB
FROM Characters
) AS b ON a.Name = b.Name
INNER JOIN (
SELECT Name, SUM(Cost) AS sumC
FROM Raid_Drops
GROUP BY Name
) AS c ON c.Name = b.Name

SQL 'merging' columns from result sets into one result set

I've been pulling my hair about how to write a particular view within the constraints of MySQL.
The following tables and columns are of importance:
CREATE TABLE `invoices` (
`id` int(10) unsigned NOT NULL AUTO INCREMENT,
PRIMARY KEY (`id`)
)
-- Joins payments to invoices. The sum of all `invoice_currency_value`s is the balance paid towards an invoice.
CREATE TABLE `financial_transactions_invoices` (
`id` int(10) unsigned NOT NULL AUTO INCREMENT,
`invoice` int(10) unsigned NOT NULL,
`invoice_currency_value` decimal(8,2) unsigned NOT NULL,
PRIMARY KEY (`id`)
)
-- Lists items (services) available to purchase.
CREATE TABLE `items` (
`id` int(10) unsigned NOT NULL AUTO INCREMENT,
`value` decimal(8,2) unsigned NOT NULL
PRIMARY KEY (`id`)
)
-- Each instance represents that the `item` has been purchased.
CREATE TABLE `item_instances` (
`id` int(10) unsigned NOT NULL AUTO INCREMENT,
`invoice` int(10) unsigned NOT NULL,
`item` int(10) unsigned NOT NULL,
`invoice_currency_rate` decimal(11,5) unsigned NOT NULL,
PRIMARY KEY (`id`)
)
-- Any number of tax instances can exist for an item instance and indicate this tax has been applied to the associated item instance.
CREATE TABLE `tax_instances` (
`id` int(10) unsigned NOT NULL AUTO INCREMENT,
`item_instance` int(10) unsigned NOT NULL,
`value` decimal(8,2) unsigned NOT NULL,
PRIMARY KEY (`id`)
)
Now, I need a view that lists for each row,
the invoice number
the total value of the invoice
the total tax on the invoice
and the total value of payments made towards the invoice
However, I can't figure out how to get these three separate queries into the same result set of one row per invoice, e.g.
inv_no total_value total_tax payments
1 150 5 120
2 120 10 20
3 10 0 10
4 1000 150 1150
I have written the following query which produces the desired result, but due to the 'no subquery' rule in MySQL views, it is not acceptable.
SELECT `invoice_id`, SUM(`total_value`) AS `total_value`, SUM(`total_tax`) AS `total_tax`,
SUM(`paid_balance`) AS `paid_balance`
FROM
(SELECT `invoices`.`id` AS `invoice_id`, SUM(`items`.`value` * `item_instances`.`invoice_currency_rate`) AS `total_value`,
NULL AS `total_tax`, NULL AS `paid_balance`
FROM `items`
JOIN `item_instances` ON `items`.`id` = `item_instances`.`item`
JOIN `invoices` ON `item_instances`.`invoice` = `invoices`.`id`
GROUP BY `invoices`.`id`
UNION
SELECT `invoices`.`id`, NULL, SUM(`tax_instances`.`value`), NULL
FROM `tax_instances`
JOIN `item_instances` ON `tax_instances`.`item_instance` = `item_instances`.`id`
JOIN `invoices` ON `item_instances`.`invoice` = `invoices`.`id`
GROUP BY `invoices`.`id`
UNION
SELECT `invoices`.`id`, NULL, NULL, SUM(`financial_transactions_invoices`.`invoice_currency_value`)
FROM `financial_transactions_invoices`
JOIN `invoices` ON `financial_transactions_invoices`.`invoice` = `invoices`.`id`
GROUP BY `invoices`.`id`) AS `components`
GROUP by `invoice_id`;
Without tackling the problem in the way I have, I can't think of any other way I can do it within MySQL.
Any ideas? Appreciate any help.
You could create two views. One with the UNION Subquery, and one with the outer query.