PHP Get data from tables that do not have a specific relationship - sql

I have two tables (CONTROL & PAYMENT) that looks like this:
CONTROL PAYMENT
+--------------------------+ +------------------------+
| CNUMBER | SERIAL | | NUMBER | STATUS |
+--------------------------+ +------------------------+
| C-200-1 | SUDU-03 | | 200 | PAID |
| C-201-1 | SUDU-03 | | 201 | PAID |
| C-202-1 | SUDU-03 | | 202 | PROCESSING|
| C-203-1 | SUDU-03 | | 203 | PAID |
| C-204-1 | SUDU-03 | | 204 | PROCESSING|
| C-204-1 | SUDU-03 | | 205 | PROCESSING|
+--------------------------+ +------------------------+
I want to show a list like this:
+--------------------------+
| CNUMBER | STATUS |
+--------------------------+
| C-200-1 | PAID |
| C-201-1 | PAID |
| C-202-1 | PROCESSING |
| C-203-1 | PAID |
| C-204-1 | PROCESSING |
| C-205-1 | PROCESSING |
+--------------------------+
So, I need get data (SELECT) from table "control" using "serial" (in control table) like a search criteria to find the "status" (in payment table) through "number" (in payment table) using %LIKE% (to match "number" and "cnumber")
I am trying but still I can't figure it out!
I hope someone can help me and give me any idea.
EDIT:
SOLUTION 1:
select c.CNUMBER,p.STATUS from CONTROL c
inner join PAYMENT p on substr(c.CNUMBER,3,3)=p.NUMBER;
Thanks to #Syscall I solved the main problem but I just have a little issue:
How I can show all the values even payment entries are null/empty ?
If the entry on 'control' exist but in 'payment' not
something like that:
+--------------------------+
| CNUMBER | STATUS |
+--------------------------+
| C-200-1 | PAID |
| C-201-1 | | <--empty
| C-202-1 | PROCESSING |
| C-203-1 | PAID |
| C-204-1 | | <--empty
| C-205-1 | PROCESSING |
+--------------------------+
EDIT 2:
SOLVED, USING LEFT JOIN
Thanks again #Syscall.
SOLUTION:
select c.CNUMBER,p.STATUS from CONTROL c
left join PAYMENT p on substr(c.CNUMBER,3,3)=p.NUMBER WHERE col1 = '$var'

You could INNER JOIN using SUBSTR :
select c.CNUMBER,p.STATUS from CONTROL c
inner join PAYMENT p on substr(c.CNUMBER,3,3)=p.NUMBER;
Outputs :
+---------+------------+
| CNUMBER | STATUS |
+---------+------------+
| C-200-1 | PAID |
| C-201-1 | PAID |
| C-202-1 | PROCESSING |
| C-203-1 | PAID |
| C-204-1 | PROCESSING |
| C-204-1 | PROCESSING |
+---------+------------+

Related

Sql server : select members having 2 or more records on different date of same class

I am trying to find out all the member ids who have more than 2 records on a different dates in the same class.
+----------+------------+-------+-----------+
| MemberId | Date | Class | |
+----------+------------+-------+-----------+
| 118111 | 2/18/2020 | A | Valid |
| 118111 | 10/15/2020 | A | Valid |
| 118216 | 1/31/2020 | B | Valid |
| 118216 | 5/16/1981 | B | Valid |
| 118291 | 6/9/2020 | A | Valid |
| 118291 | 12/5/2020 | A | Valid |
| 118533 | 4/9/2020 | A | Not valid |
| 118533 | 11/11/2020 | B | Not valid |
| 118533 | 7/22/2020 | C | Valid |
| 118533 | 10/25/2020 | C | Valid |
| 118293 | 3/30/2020 | A | Not valid |
| 118293 | 3/30/2020 | A | Not valid |
| 118499 | 4/16/2020 | B | Valid |
| 118499 | 7/26/2020 | B | Valid |
| 118499 | 3/25/2020 | A | Not valid |
+----------+------------+-------+-----------+
I have made a query which checks only 2 records but unable to find a solution for checking more than 2 records.
select mc.*
FROM table1 AS mc
JOIN table1 AS ma ON ma.memberid = mc.memberid
AND ma.date != mc.date
AND ma.class = mc.class
Assuming you just want the memberid you can us a HAVING:
SELECT memberid
FROM dbo.YourTable
GROUP BY memberid
HAVING COUNT(DISTINCT [Date]) > 2;

Create calculated field based on previous rows Oracle SQL

I am trying to create a manually calculated column where I keep track of a current inventory.
Currently, I have a table that looks like this:
| Group | Part | Operation Type | Transaction Amount |
|--------------|------|----------------|--------------------|
| Concrete | A | STOCK | 100 |
| Concrete | A | Buy | 25 |
| Concrete | A | Make | -10 |
| Concrete | A | Make | -10 |
| Concrete | A | Make | -10 |
| Concrete | A | Make | -10 |
| Concrete | A | Make | -10 |
| Concrete | B | STOCK | -10 |
| Concrete | B | Make | -10 |
| Concrete | B | Make | -10 |
| Concrete | B | Make | -10 |
| Concrete | B | Make | -10 |
| Concrete | B | Make | 150 |
| Construction | C | STOCK | 10 |
| Construction | C | Make | -1 |
| Construction | C | Make | -1 |
| Construction | C | Make | -1 |
| Construction | C | Make | -1 |
| Construction | D | STOCK | 5 |
| Construction | D | Make | -5 |
The table is first ordered by group then by part, and then STOCK is always shown as the first value. The idea is to create a new manually calculated column, curr_inventory, that allows for us to keep track of current inventory and see if or when our inventory for a given part, for a given group, dips below 0.
Ideally, the end results would look like this:
| Group | Part | Operation Type | Transaction Amount | New_Inventory_Column |
|:------------:|:----:|:--------------:|:------------------:|:--------------------:|
| Concrete | A | STOCK | 100 | 100 |
| Concrete | A | Buy | 25 | 125 |
| Concrete | A | Make | -10 | 115 |
| Concrete | A | Make | -10 | 105 |
| Concrete | A | Make | -10 | 95 |
| Concrete | A | Make | -10 | 85 |
| Concrete | A | Make | -10 | 75 |
| Concrete | B | STOCK | 10 | 10 |
| Concrete | B | Make | -10 | 0 |
| Concrete | B | Make | -10 | -10 |
| Concrete | B | Make | -10 | -20 |
| Concrete | B | Make | -10 | -30 |
| Concrete | B | Make | 150 | 120 |
| Construction | C | STOCK | 10 | 10 |
| Construction | C | Make | -1 | 9 |
| Construction | C | Make | -1 | 8 |
| Construction | C | Make | -1 | 7 |
| Construction | C | Make | -1 | 6 |
| Construction | D | STOCK | 5 | 5 |
| Construction | D | Make | -5 | 0 |
The end result would be a column that initiates when the part number has changed and the operation type is STOCK, and then begins to calculate (using the transaction amount) what the current inventory is.
I am not sure where to start on a SQL query that would allow for this. Intuitively, the pseudocode would look something like:
for each row in table:
if operation_type == "stock":
curr_inv = stock.value
else:
curr_inv = previous_curr_inv + transaction_amount
However, I am not sure how to even begin writing SQL for this. I typically try to post what SQL I am working with but I don't even know where to begin. I have looked at various posts online, on SO, including posts like this, and this, and this, but I could not see how the selected answers could be used as a solution.
I used the window function to calculate the running total.
I added the row_number column in the subquery.
Try this:
select t1."Group",t1."Part",t1."Operation Type", t1."Transaction Amount",
sum(t1."Transaction Amount") over (partition by t1."Group",t1."Part" order by t1.rownumber)
from (
select row_number() over (order by null) as rownumber, t.*
from test t ) t1
Test Result:
DB<>Fiddle
SQL tables represent unordered sets. To put things in order, you need a column with the ordering. In the code below, I will use ? for this column.
Then you want a cumulative sum:
select t.*,
sum(case when operation_type in ('STOCK'),
when operation_type in ('Make') then - amount
when operation_type in ('Buy') then - amount
else 0
end) over (partition by group, part order by ?)
from t;

Outer Join multible tables keeping all rows in common colums

I'm quite new to SQL - hope you can help:
I have several tables that all have 3 columns in common: ObjNo, Date(year-month), Product.
Each table has 1 other column, that represents an economic value (sales, count, netsales, plan ..)
I need to join all tables on the 3 common columns giving. The outcome must have one row for each existing combination of the 3 common columns. Not every combination exists in every table.
If I do full outer joins, I get ObjNo, Date, etc. for each table, but only need them once.
How can I achieve this?
+--------------+-------+--------+---------+-----------+
| tblCount | | | | |
+--------------+-------+--------+---------+-----------+
| | ObjNo | Date | Product | count |
| | 1 | 201601 | Snacks | 22 |
| | 2 | 201602 | Coffee | 23 |
| | 4 | 201605 | Tea | 30 |
| | | | | |
| tblSalesPlan | | | | |
| | ObjNo | Date | Product | salesplan |
| | 1 | 201601 | Beer | 2000 |
| | 2 | 201602 | Sancks | 2000 |
| | 5 | 201605 | Tea | 2000 |
| | | | | |
| | | | | |
| tblSales | | | | |
| | ObjNo | Date | Product | Sales |
| | 1 | 201601 | Beer | 1000 |
| | 2 | 201602 | Coffee | 2000 |
| | 3 | 201603 | Tea | 3000 |
+--------------+-------+--------+---------+-----------+
Thx
Devon
It sounds like you're using SELECT * FROM... which is giving you every field from every table. You probably only want to get the values from one table, so you should be explicit about which fields you want to include in the results.
If you're not sure which table is going to have a record for each case (i.e. there is not guaranteed to be a record in any particular table) you can use the COALESCE function to get the first non-null value in each case.
SELECT COALESCE(tbl1.ObjNo, tbl2.ObjNo, tbl3.ObjNo) AS ObjNo, ....
tbl1.Sales, tbl2.Count, tbl3.Netsales

In SSRS, how can I SUM by multiple groups?

Please refer to the below table:
+----------------------------------------------------------+
| +-----------+--------------------+---------------------+ |
| | Company | GL Account | Amount | |
| +-----------+--------------------+---------------------+ |
| | Company 1 | Cash at Bank ANZ | $500,452.22 | |
| +-----------+--------------------+---------------------+ |
| | | Westpac Investment | $443,233.32 | |
| +-----------+--------------------+---------------------+ |
| | | NAB Cheque | $9,833.22 | |
| +-----------+--------------------+---------------------+ |
| | Company 2 | Cash at Bank ANZ | $938.22 | |
| +-----------+--------------------+---------------------+ |
| | | Investment Online | $940,404,400.20 | |
| +-----------+--------------------+---------------------+ |
| | Company 3 | Online Advantage | $93,393.00 | |
| +-----------+--------------------+---------------------+ |
| | | Direct Access | $30.30 | |
| +-----------+--------------------+---------------------+ |
| | | BAR Invest | $192,330,303,300.10 | |
| +-----------+--------------------+---------------------+ |
| | TOTAL | | $193,271,755,580.58 | |
| +-----------+--------------------+---------------------+ |
+----------------------------------------------------------+
This above table is what my SSRS report currently looks like.
As you can see, I have a group of companies. Each company has GL Accounts with multiple transactions however, I am only displaying the total for each GL account. For example, the top amount field "$500,452.22" is a total of ALL transactions for "Cash at Bank ANZ" for "Company 1". Furthermore, I have a total at the bottom, which is the total of ALL amount totals.
I want to add an additional total field which shows the total for ALL amounts fore each company. Basically, the report should look like this:
+----------------------------------------------------------+
| +-----------+--------------------+---------------------+ |
| | Company | GL Account | Amount | |
| +-----------+--------------------+---------------------+ |
| | Company 1 | Cash at Bank ANZ | $500,452.22 | |
| +-----------+--------------------+---------------------+ |
| | | Westpac Investment | $443,233.32 | |
| +-----------+--------------------+---------------------+ |
| | | NAB Cheque | $9,833.22 | |
| +-----------+--------------------+---------------------+ |
| | | TOTAL | $953,518.76 | |
| +-----------+--------------------+---------------------+ |
| | Company 2 | Cash at Bank ANZ | $938.22 | |
| +-----------+--------------------+---------------------+ |
| | | Investment Online | $940,404,400.20 | |
| +-----------+--------------------+---------------------+ |
| | | TOTAL | $940,405,338.42 | |
| +-----------+--------------------+---------------------+ |
| | Company 3 | Online Advantage | $93,393.00 | |
| +-----------+--------------------+---------------------+ |
| | | Direct Access | $30.30 | |
| +-----------+--------------------+---------------------+ |
| | | BAR Invest | $192,330,303,300.10 | |
| +-----------+--------------------+---------------------+ |
| | | TOTAL | $192,330,396,723.40 | |
| +-----------+--------------------+---------------------+ |
| | TOTAL | | $193,271,755,580.58 | |
| +-----------+--------------------+---------------------+ |
+----------------------------------------------------------+
Every time I try to create this total field, the report just displays duplicates of each GL Account total and not the total of all amounts per company.
Can anyone explain how to add the field that I want?
FYI: This is the SQL Query that I used:
select GLAC.GLCo as Company, HQCO.Name as 'Company Name', GLAC.Description as 'GL Description', GLDT.Amount as Amount from GLAC
LEFT JOIN HQCO ON
GLAC.GLCo = HQCO.HQCo
LEFT JOIN GLDT ON
GLAC.GLCo = GLDT.GLCo and GLAC.GLAcct = GLDT.GLAcct
where udCategory = 'Cash At Bank' and Active = 'Y' and (GLAC.GLCo = 1 or GLAC.GLCo = 5 or GLAC.GLCo = 6 or GLAC.GLCo = 7)
Managing groups went from really simple in SSRS 2005 to very difficult and arcane in SSRS 2008. Adding a footer to a group is the least intuitive UX ever.
To create a header or footer after the group has been created, go to the bottom of the design window where the Row Groups panel is. This will show your groups. Drop down the arrow on the Detail group (not the actual group you want to add the footer to but the group inside that) and you will see Add Total with a menu of Before or After. Before adds a header and After adds a footer to the group that encloses the item you are adding the total to.
Once the footer has been created put the expression =SUM(Fields!Amount.Value) into the column and it will sum the amount for your group.
If I recall correctly there is an option in SSRS 2008 R2 to add group sub-totals to a tablix when you add the group.
If you're trying to add them after the fact you can create a group footer row and then put your =SUM(Field!Amount.Value) in the Amount column and just hardcode the TOTAL text in the GL Account column. Since this is still being done inside the scope of the grouping it will only SUM() the values for that group.
I think that , the 'Total' that you are looking will be equal to the sum of all Amount in the data set. I think this should work.
1. Add a subtotal row
2. List item give its expression as SUM(Field!Amount.value)
Grouping in SSRS is certainly not intuitive.
I managed to achieve what I wanted by right clicking in the "Amount" field and then selecting "Insert Row" --> "Outside Group (Below)". I then put the sum in the new cell and everything was calculated how I desired.

how to make the data sorts like this on sql server

I've a data that looks like this
| FormCode | Description | MenuPath |
+----------+----------------------+-------------+
| PY | Payroll | |
| PD | Personal Development | |
| EM | EmployeeMaster | PY |
| EB | EmployeeBank | PY |
| ED | EmployeeData | PY |
| Report | Report | PY |
| Badge | Badge Report | PY/Report |
| Process | Process | PY |
| Bonus | Bonus Component | PY/ED |
|Preference| Preference | PY |
| Tax | Tax Result | PY/ED |
|FinalBonus| FinalBonus | PY/ED/Bonus |
| Annual | Annual Process | PY/Process |
|BonusbyCC | Bonus by Cost Centre | PY/ED/Bonus |
| Period | Period |PY/Preference|
I want this data sort to be like this below.
| FormCode | Description | MenuPath |
+----------+----------------------+-------------+
| PY | Payroll | |
| EB | EmployeeBank | PY |
| ED | EmployeeData | PY |
| Bonus | Bonus Component | PY/ED |
|BonusbyCC | Bonus by Cost Centre | PY/ED/Bonus |
|FinalBonus| FinalBonus | PY/ED/Bonus |
| Tax | Tax Result | PY/ED |
| EM | EmployeeMaster | PY |
|Preference| Preference | PY |
| Period | Period |PY/Preference|
| Process | Process | PY |
| Annual | Annual Process | PY/Process |
| Report | Report | PY |
| Badge | Badge Report | PY/Report |
| PD | Personal Development | |
That's the result of the sorting
Explanation :
I will try to explain the sorting. At first we look at the formcode. it will put PY on the first row. After that, there will be the row where MenuPath was PY (sort by alphabeth on the description). In this case EmployeeBank show first. If it doesn't have any child path, the next row will be EmployeeData. after that, EmployeeData has a child like we could see there's Bonus Component(sort by Description) on the next row. After that, if it doesn't have any child, the next row will be Tax Result, but as you can see, Bonus Component still has a child (Bonus by Cost Centre and FinalBonus) so this 2 data will appear after Bonus Component. Tax Result will appear next. The process will keep like that until the end of data.
Sorry if my english messed up and my explanation not good at all. If anyone understand what I mean and could fix my english on the explanation please do it
Thanks for the help
There is absolutely no logic to sort in a way in which you have shown us ..however you can achieve so by assigning some kind of ID to your field and then sort on it
SELECT * FROM Table1
ORDER BY CASE [FormCode]
WHEN 'PY' THEN 1
WHEN 'EM' THEN 2
WHEN 'EB' THEN 3
WHEN 'ED' THEN 4
WHEN 'Bonus' THEN 5
WHEN 'BonusbyCC' THEN 6
WHEN 'FinalBonus' THEN 7
WHEN 'Tax' THEN 8
WHEN 'Preference' THEN 9
WHEN 'Period' THEN 10
WHEN 'Process' THEN 11
WHEN 'Annual' THEN 12
WHEN 'Report' THEN 13
WHEN 'Badge' THEN 14
WHEN 'PD' THEN 15
END;
SAMPLE FIDDLE