SQL join from the same table - sql

How do I get grand total for orders made by credit card only from such a table :
order_id | meta_name | meta_value
___________________________________
1 | type | credit
1 | total | 1030.00
...
2 | type | check
2 | total | 930.00
..
3 | type | credit
3 | total | 330.00
what is the best way to describe such select operation if you are to search the Internet for a solution to this problem.
suppose I am MySQL.

You can do this with either join or group by. Here is the join method:
select ttype.order_id, cast(ttotal.meta_value as money)
from table ttype join
table ttotal
on ttype.order_id = ttotal.order_id and
ttype.meta_name = 'type' and
ttype.meta_value = 'credit' and
ttotal.meta_name = 'total';
If yo could have more than one total for an order, then you would still want to aggregate:
select ttype.order_id, sum(cast(ttotal.meta_value as money))
from table ttype join
table ttotal
on ttype.order_id = ttotal.order_id and
ttype.meta_name = 'type' and
ttype.meta_value = 'credit' and
ttotal.meta_name = 'total'
group by ttype.order_id

Related

Calculation view for material to material transfer

I have a table Tab1 with two rows
+-------+----------+--------------+----------+--------+
| DOC# | Material | Debit/Credit | Quantity | Amount |
+-------+----------+--------------+----------+--------+
| 12345 | A1 | Credit | 5 | 50 |
| 12345 | B1 | Debit | 5 | 50 |
+-------+----------+--------------+----------+--------+
Desired Result
+-------+---------------+-------------+----------+--------+
| DOC# | From Material | To Material | Quantity | Amount |
+-------+---------------+-------------+----------+--------+
| 12345 | A1 | B1 | 5 | 50 |
+-------+---------------+-------------+----------+--------+
I am working on SAP HANA, writing a calculation view.
You can use conditional aggregation as follows:
Select doc#,
Max(case when debit_credit = 'credit' then material end) as from_material,
Max(case when debit_credit = 'debit' then material end) as to_material,
Quantity, Amount
From t
Group by doc#, quantity, amount
An alternative to aggregation is a self-join. I guess that is easy to understand for beginners. You join the credit rows to the debit rows, as if these were two different tables.
select
doc_number, quantity, amount,
debit.material as from_material,
credit.material as to_material
from (select * from tab1 where credit_debit = 'Credit') as credit
join (select * from tab1 where credit_debit = 'Debit') as debit
using (doc_number, quantity, amount)
order by doc_number, quantity, amount;
It may be that HANA lacks the USING clause. Then the query would become
select
credit.doc_number, credit.quantity, credit.amount,
debit.material as from_material,
credit.material as to_material
from (select * from tab1 where credit_debit = 'Credit') as credit
join (select * from tab1 where credit_debit = 'Debit') as debit
on credit.doc_number = debit.doc_number
and credit.quantity = debit.quantity
and credit.amount = debit.amount
order by credit.doc_number, credit.quantity, credit.amount;

SQL Query To See if Sums Dont Add Up

I have the two tables below is in a database
Is there a SQL query that can get all the invoicesamounts from the invoice detail table and see if the sum of the detailamount based on the invoicenum dont add up to the total invoiceamount to the corresponding invoice number in the invoice table?
Invoice Table
invoicenum | invoicedate | invoiceamount
-----------+-------------+--------------
00551198 | 1/1/2014 | $150.5
00551199 | 1/2/2014 | $10
invoiceDetail Table
invoicenum | trackingno | detailamount
-----------+--------------------+-------------
00551198 | 1Z2F12346861507266 | $50
00551198 | 1Z2F12346861507267 | $80
00551198 | 1Z2F12346861507268 | $20.5
00551199 | 1Z2F12346861503423 | $10.5
An aggregation and join should do the trick:
select i.*, id.sumdetail
from invoices i left join
(select id.invoicenum, sum(detailamount) as sumdetail
from invoicedetail id
group by id.invoicenum
) id
on i.invoicenum = id.invoicenum
where id.sumdetail <> i.invoicenum or id.sumdetail is null;
Here's your query
select *, case when t1.s=i.invoiceamount then 'equal' else 'not equal' end from invoice i
left join
(select sum(detailamount) as s, invoicenum from invoicedetail group by invoicenum) as t1
on t1.invoicenum = i.invoicenum

change and merge multiple values on column if there is duplicate value in other columns

Sorry, I'm new to SQL..I'm using Sybase Central
I need help, I'm currently stuck on data table from select statement (stored procedure) like this :
select case when product like 'A%' then 'Product A' when product like 'B%'
then 'Product B' else 'Product C' end as
'ProductGroup',product,invoice,customer from data_sales
group by product,invoice,customer
Results :
+--------------+---------+---------+---------+
| ProductGroup | Product | Invoice | Customer|
+--------------+---------+---------+---------+
| Product A | A1 | INV001 | MR.A |
| Product A | A1 | INV002 | MR.B |
| Product B | B1 | INV002 | MR.B |
| Product B | B1 | INV003 | MR.C |
+--------------+---------+---------+---------+
I want to merge and change the value into Product C in ProductGroup column, if there is duplicate values on Invoices or Customers columns
Results should be like this :
+--------------+--------+---------+
| ProductGroup | Invoice| Customer|
+--------------+--------+---------+
| Product A | INV001 | MR.A |
| Product C | INV002 | MR.B |
| Product B | INV003 | MR.C |
+--------------+--------+---------+
I've been using case when and group by method, but it's still showing duplicate results
Any help would be really appreciated
Thank you
The below query does check the invoices or customers for duplicates done via group by. Grouping invoices will group the repeated invoices and will give the aggregate count as greater than 1 if found repeated else 0 similarly in or condition for customers. Is this what you want ?
Update Table
Set Product="Product C" where
Invoice In
(Select Invoice
from table group by
Invoice having
count(*)>1) or
Customers In (Select Customers
from table group by
Customers having
count(*)>1)
You can check the duplicates by having count(*)>1 clause with group by
update tab t
set ProductGroup = 'Product C'
where exists (
select 1
from tab tt
where exists ( select Invoice
from tab
where Invoice = tt.Invoice
group by Invoice
having count(*)>1 )
or exists ( select Customer
from tab
where Customer = tt.Customer
group by Customer
having count(*)>1 ) )
If you just want a query which returns the requested information (so no update):
select distinct CASE WHEN (select count()
from Tab t2
where t2.Customer = t1.Customer or t2.Invoice = t1.Invoice) > 1
THEN 'Product C'
ELSE ProductGroup
END "ProductGroup", Invoice, Customer
from Tab t1

SQL Display details and count fields through checks

I have created an Oracle database which contains information regarding renting flats/apartments. I am trying to create a SQL script which will, first, count how many students have not paid their first invoice (so there should be an "is not null" check on this field) and, second, display their details.
Here is an example of the data the table is called INVOICE:
+-----------+-------+---------------+---------------+----------------+--------+---------------+-------------+
| INVOICEID | PRICE | PAYMENTMETHOD | FIRSTREMINDER | SECONDREMINDER | RENTID | PAYMENTSTATUS | DATESENT |
+-----------+-------+---------------+---------------+----------------+--------+---------------+-------------+
| 1 | 415 | Visa | 10/FEB/2016 | - | 1 | Paid | 15/MAR/2016 |
| 2 | 600 | Cash | 15/FEB/2016 | - | 2 | Unpaid | 12/MAR/2016 |
| 3 | 750 | Visa | 10/FEB/2016 | 15/MAR/2016 | 1 | Paid | 15/MAR/2016 |
+-----------+-------+---------------+---------------+----------------+--------+---------------+-------------+
Using this data, the SQL statement should return the details for number 2 in the table and count them.
I'd be grateful if anyone could help with this because I have no clue where to start. SQL is not my main programming language.
It seems this should suffice...
To get the count:
select count(*) from invoice where paymentstatus = 'Unpaid'
To get the details for those rows:
select * from invoice where paymentstatus = 'Unpaid'
You mentioned something about an "is not null" check "on this field" - what field are you referring to? Isn't the paymentstatus column sufficient?
The query below enumerates the invoice #'s per RENTID and allows you to select 1st invoices that were unpaid:
select * from (
select *,
row_number() over (partition by rentid order by invoiceid) invoice_number
from mytable
) t where invoice_number = 1 and paymentstatus = 'Unpaid'
If you just want the count, then replace select * with select count(*)
select count(*) from (
select *,
row_number() over (partition by rentid order by invoiceid) invoice_number
from mytable
) t where invoice_number = 1 and paymentstatus = 'Unpaid'
Another way that checks whether secondreminder is null to determine whether an invoice is a 1st invoice
select count(*)
from mytable
where secondreminder is null
and paymentstatus = 'Unpaid'

SUM in multi-currency

I am trying to do SUM() in a multi-currency setup. The following will demonstrate the problem that I am facing:-
Customer
-------------------------
Id | Name
1 | Mr. A
2 | Mr. B
3 | Mr. C
4 | Mr. D
-------------------------
Item
-------------------------
Id | Name | Cost | Currency
1 | Item 1 | 5 | USD
2 | Item 2 | 2 | EUR
3 | Item 3 | 10 | GBP
4 | Item 4 | 5 | GBP
5 | Item 5 | 50 | AUD
6 | Item 6 | 20 | USD
7 | Item 3 | 10 | EUR
-------------------------
Order
-------------------------
User_Id | Product_Id
1 | 1
2 | 1
1 | 2
3 | 3
1 | 5
1 | 7
1 | 5
2 | 6
3 | 4
4 | 2
-------------------------
Now, I want the output of a SELECT query that lists the Customer Name and the total amount worth of products purchased as:-
Customer Name | Amount
Mr. A | Multiple-currencies
Mr. B | 25 USD
Mr. C | 15 GBP
Mr. D | 2 EUR
So basically, I am looking for a way to add the cost of multiple products under the same customer, if all of them have the same currency, else simply show 'multiple-currencies'. Running the following query will not help:-
SELECT Customer.Name, SUM(Item.Amount) FROM Customer
INNER JOIN Order ON Order.User_Id = Customer.Id
INNER JOIN Item ON Item.Id = Order.Product_Id
GROUP BY Customer.Name
What should my query be? I am using Sqlite
I would suggest two output columns, one for the currency and one for the amount:
SELECT c.Name,
(case when max(currency) = min(currency) then sum(amount)
end) as amount,
(case when max(currency) = min(currency) then max(currency)
else 'Multiple Currencies'
end) as currency
FROM Customer c INNER JOIN
Order o
ON o.User_Id = c.Id INNER JOIN
Item
ON i.Id = o.Product_Id
GROUP BY c.Name
If you want, you can concatenate these into a single string column. I just prefer to have the information in two different columns for something like this.
The above is standard SQL.
I think your query should looks like this
SELECT
Data.Name AS [Customer Name],
CASE WHEN Data.Count > 1 THEN "Multiple-currencies" ELSE CAST(Data.Amount AS NVARCHAR) END AS Amount
FROM
(SELECT
Customer.Name,
COUNT(Item.Currency) AS Count,
SUM(Item.Amount) AS Amount
FROM
Customer
INNER JOIN Order ON Order.User_Id = Customer.Id
INNER JOIN Item ON Item.Id = Order.Product_Id
GROUP BY
Customer.Name) AS Data
A subquery to get the count of currencies and then ask for them in the main query to show the total or the text "Multiple-currencies".
Sorry if there is any mistake or mistype but I don't have a database server to test it
Hope this helps.
IMO I would start by standardizing variable names. Why call ID in customer table USER_ID in order table? Just a pet peeve. Anyway, you should learn how to build queries.
start with joining the customer table to the order table on then join the result to the item table. The first join is on CUSTOMER_ID and the second join is on PRODUCT_ID. Once you have that working use SUM and GROUP BY
Ok, I managed to solve the problem this way:-
SELECT innerQuery.Name AS Name, (CASE WHEN innerQuery.Currencies=1 THEN (innerQuery.Amount || innerQuery.Currency) ELSE 'Mutliple-Currencies' END) AS Amount, FROM
(SELECT Customer.Name, SUM(Item.Amount), COUNT(DISTINCT Item.Currency) AS Currencies, Item.Currency AS Currency FROM Customer
INNER JOIN Order ON Order.User_Id = Customer.Id
INNER JOIN Item ON Item.Id = Order.Product_Id
GROUP BY Customer.Name)innerQuery