Create views from tables with different number of columns mysql - mysql

I'm new to views in MySQL server.
I'm trying to create two VIEWS with "invoice_head" and "invoice_body", but in order to do that i need to get different keys from different tables (this tables have diferent number of columns).
This is the code that i'm trying to use:
CREATE VIEW invoice_head AS
SELECT
date_order AS 'DATE OF ISSUE'
FROM orders
UNION ALL
SELECT
customer_name AS 'Client Name',
customer_address AS 'Street adress',
customer_district AS 'District',
customer_country AS 'Portugal',
customer_zipcode AS 'ZIP Code'
FROM customer;
but this code is giving me the error: The used SELECT statements have different number of columns.
And the tables i'm using are something like this (for example)
Customer Table (8 columns)
customer_id
customer_name
customer_address
customer_district
(...)
1
maria xxx
street xxx
lisbon
(...)
Orders Table (9 columns)
order_id
customer_id
product_id
date_order
(...)
10
1
20
2020-12-15
(...)
The invoice_head is supposed to have information about the customer, the invoice_id, and the date of the order (invoice_date aka date_order).
Can someone tell me in what way is this possible to be made?
Is it impossible to do or I need to do something I'm not seeing?

Someone in the comments helped me. I just needed to use the "Join" instead of "Select":
DROP VIEW IF EXISTS `invoice_head`;
CREATE VIEW `invoice_head` AS
SELECT date_order as `Date of issue`,
customer_name AS `Client Name`,
customer_address AS `Street adress`,
customer_district AS `District`,
customer_country AS `Country`,
customer_zipcode AS `ZIP Code`
FROM orders
join customer
on orders.customer_id = customer.customer_id;

Related

how to connect two different table having similar foreign key?

I am creating an accounting module with laravel and mysql. For that, I've master table called 'bills' which has some columns regarding invoice informations and id as primary key. Now I've two different tables called 'payments' having bill_id as foreign key and 'debitnotes' also having bill_id as foreign key.
Now I want to show payment history of particular bill which is paid. In order to that, I've to retrieve information from both payments table and debitotes table based on bill id at once! Now, my question is: How can I achieve this without writing multiple queries?
bills table has columns:
id
bill_number
vendor_id
amount
amount_payable
date
payments table has columns:
id
bill_id
transaction_number
amount
date
vendor_id
debitnotes table has columns:
id
bill_id
debit_note_number
amount
vendor_id
date
I want to show both payments and debitnotes of particular bills in single page. How can i achieve this?
Use a union:
select
'bill' source,
id,
bill_number number,
vendor_id,
amount,
amount_payable,
date
from bills
union all
'payment',
id,
transaction_number,
vendor_id,
-amount amount, -- assuming payments cause the balance to lower
null,
date
from payments
union all
'debitnote',
id,
debit_note_number,
vendor_id,
amount,
null,
date
from debitnotes
You should delete the vendor_id column from payments and debitnotes because it is redundant (or denormalized); it can be found by joining to the bill table.
You should use join clause, and for payments and debitnotes, you can prepend the table name.
Here is an example from documentation:
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')
->select('users.*', 'contacts.phone', 'orders.price')
->get();

Mysql Sum one row only once - with Group By

I have a seemingly simple problem that I can't seem to solve. Imagine an order table with a shipping value for that order. And imagine an item table that point to the order, and have a price:
Order
|id |created |shipping|
|---|----------|--------|
|101|2018-01-01|10 |
|102|2018-01-01|10 |
Item
|order_id|price |
|--------|--------|
|101 |1 |
|101 |2 |
|102 |3 |
So there were two orders. Each had a shipping fee of $10. One order had two items, priced $1 and $2. The other had one item priced $3. Very simple so far.
I want to write a query, that will find the total shipping price and the total item price (summed) for every day (group by created). Naively, I would write this query:
SELECT
o.created, sum(o.shipping), sum(i.price)
FROM
test_order o,
test_item i
WHERE
i.order_id = o.id
group by o.created
This query is very simple. It joins the two tables, and then group by that date, and sums vertically. The problem is with the shipping part. Since there are three rows after the join, there are three $10 shipping fees in the sum, which is entirely incorrect.
I could add a distinct to my shipping clause (sum(distinct o.shipping)), but that, too, is incorrect. It would evaluate those three 10s, and only keep one, resulting in a summed value of $10. It doesn't recognize that two of those 10s came from one source row, while the third 10 comes from an entirely different source row, and is desirable to include it in the sum.
My real query is much more complicated that this, but I distilled it down to this. I would think this is a common situation for many use cases. Of course, I could write a second query (or a sub query), but I'd like to not do that if at all possible.
Wanna play with this data yourself? Here is the sql:
CREATE TABLE IF NOT EXISTS `test_item` (
`order_id` int(11) NOT NULL,
`price` int(11) NOT NULL)
INSERT INTO `test_item` (`order_id`, `price`) VALUES (101, 1), (101, 2), (102, 3);
CREATE TABLE IF NOT EXISTS `test_order` (
`id` int(12) NOT NULL,
`created` datetime NOT NULL,
`shipping` int(11) NOT NULL,
PRIMARY KEY (`id`)
)
INSERT INTO `test_order` (`id`, `created`, `shipping`) VALUES (101, '2018-01-01 00:00:00', 10), (102, '2018-01-01 00:00:00', 10);
Thanks!
You are trying to avoid subqueries, but in this case I can't see other options:
SELECT created, sum(shipping), sum(price) from (
SELECT
o.created, o.shipping, sum(i.price) as price
FROM
test_order o,
test_item i
WHERE
i.order_id = o.id
group by o.created, o.id) subquery;
Here the fiddle.
Using intermediate alias table would do the trick :
select sumTable.createdDate, sum(sumTable.shippingSum),sum(sumTable.priceSum) from (
SELECT
o.created, (o.shipping) as shippingSum, sum(i.price) as priceSum
FROM
test_order o,
test_item i
WHERE
i.order_id = o.id
group by o.created,o.id)
as sumTable
I tested in SQL Fiddle over here resulting in sum of $30 and $6, which is probably what you wanted.

Prepending a row in the result of a MySQL query?

Reading this answer to a SO question on how to append a row onto a MySQL result, we can do the following to append the value Jason to the names of Customers:
Select NAME
From Customers
UNION ALL
Select 'Jason'
So we end up with:
NAME
Actual Customer 1
Actual Customer 2
Jason
But how could we add Jason to the beginning of the results so what we have:
NAME
Jason
Actual Customer 1
Actual Customer 2
(Would like to do this without using Order By)
Have you tried this
Select 'Jason' As `Name`
UNION ALL
Select Name
From Customers
If you want the second query ordered then use something like
Select 'Jason' As `Name`
UNION ALL
(Select `myDate`
From Customers
Order By `myDate`
)

How to select count of records from order and order line tables group by date?

My system has Order and OrderLine tables.
We can consider them as follows:
(Please don't consider the syntax part).
Order:
OrderId int(11) not null auto increment
customerId int(11)
orderdate datetime
...
OrderLine:
OrderId int(11)
productId int(11)
orderdate datetime
rate, total, ...
I need a hint / pointer to write a query in MySQL which can give me total number of orders and items (which are part of orderlines) grouped by orderdate. In other words, I need a query which can display information from two different tables (basically, some counts) which are not 1:1 (Eg: in this case, one order can consist of many items). What I need is only the count. The relationship between the tables is OrderId. But, that is not relevant to me as I need to look at OrderDate and group them in both the tables.
Eg:
Date Orders Items
2015-08-10 4747 58729
2015-08-11 4822 47593
2015-08-12 5219 52842
What I have done so far is something like this:
Select count(*) from order group by date(orderdate)
Select count(*) from orderline group by date(orderdate)
I also tried joining using LEFT join. But, I could not get the desired results.
Any help in combining the data (mainly count) of multiple tables in a single select will help me.
Let me know if you need more information.
You need to use subselect for counting orderline - something like this:
select date(orderdate),count(*),
(select count(*) from OrderLine
where date(OrderLine.orderdate)=date(Order.orderdate))
from Order
group by date(orderdate);

Filtering SQL table to display totals based on an "invoice_status"

Background: I am developing some stored procedures for a project and want to display a sum total of earnings based on specific criteria dictated by a column I created called "invoice_status"--this column has the datatype ENUM and only allows for names like "Delivered", "Processing", and "Shipping"
I am looking to create a procedure that displays the total earnings on invoices that are listed as "Delivered". Here's my sql so far:
select invoice_id, total_cost, invoice_status from invoice
union
select count(invoice_id), sum(total_cost), null
from invoice;
I tried filtering the results using "where invoice_status = "Delivered"", but this doesn't affect the sum and count values
Any ideas?
you need the condition on both queries
select invoice_id, total_cost, invoice_status from invoice
where invoice_status = "Delivered"
union
select count(invoice_id), sum(total_cost), null
from invoice
where invoice_status = "Delivered";