Change in foreign table affect the previous report - sql

Actually I am stuck in one issue. I have a table:
tbl_color
+------------+
|id | name |
|---|--------|
|1 | Red |
|---|--------|
|2 | Blue |
|---|--------|
|3 | Black |
+------------+
tbl_clothes
+----------------+
|id | name |
| 1 | Pant |
| 2 | Shirt |
| 3 | T-shirt |
+----------------+
tb_sales
+---------------------------------------+
|id | id_cloth | id_color | sales_date |
|---|----------|-----------|------------|
|1 | 1 | 1 | 2016/1/1 |
|---|----------|-----------|------------|
|2 | 1 | 3 | 2016/1/1 |
|---|----------|-----------|------------|
|3 | 1 | 1 | 2016/2/2 |
+---------------------------------------+
So when I change one row of tbl_color to
tbl_color
+---------------------------+
|id | name | modified_on |
|----|--------|-------------|
|1 | Orange | 2016/3/2 |
|----|--------|-------------|
|2 | Blue | 2016/1/2 |
|----|--------|-------------|
|3 | Black | 2016/1/2 |
+---------------------------+
So when I want to get report of sales on 2016/1/1
SELECT * from table tb_sales
JOIN tbl_clothes ON tbl_clothes.id = tbl_sales.id_cloth
JOIN tbl_sales ON tbl_color.id = tbl_sales.id_color
where sales_date = '2016/1/1'
I get the report that have been modified no the original sales
How can I handle this issue?

Related

How to group a set of records (i.e. into a invoice / billing cycle)

For a set of invoice stage records by project I'm trying to determine a billing cycle using the ID of the starting invoice stage.
Here's the table - InvoiceStages
|ID| Project | StageDate | InvoiceStage | StageFlag | BillCycle |
|1 | abc123 | 10-May-18 | Finance | S | 1 |
|2 | abc123 | 15-May-18 | Review Draft | | 1 |
|4 | abc123 | 19-May-18 | Approved - NO Changes | | 1 |
|7 | abc123 | 21-May-18 | Final Invoice | E | 1 |
|9 | abc123 | 05-Jun-18 | Finance | S | 9 |
|12| abc123 | 07-Jun-18 | Review Draft | | 9 |
|15| abc123 | 09-Jun-18 | Approved - With Changes | | 9 |
|21| abc123 | 10-Jun-18 | Review Draft | | 9 |
|25| abc123 | 12-Jun-18 | Approved - NO Changes | | 9 |
|40| abc123 | 13-Jun-18 | Final Invoice | E | 9 |
|3 | xyz789 | 15-May-18 | Finance | S | 3 |
|5 | xyz789 | 19-May-18 | Review Draft | | 3 |
|6 | xyz789 | 20-May-18 | Approved - NO Changes | | 3 |
|8 | xyz789 | 22-May-18 | Final Invoice | E | 3 |
|10| xyz789 | 06-Jun-18 | Finance | S | 10 |
|11| xyz789 | 07-Jun-18 | Review Draft | | 10 |
|18| xyz789 | 09-Jun-18 | Approved - NO Changes | | 10 |
|22| xyz789 | 11-Jun-18 | Final Invoice | E | 10 |
I've looked at LAG / LEAD but wasn't sure if that would be the best option.
Select
ID
, Project
, StageDate
, InvoiceStage
, StageFlag
, ?? As BillCycle
From InvoiceStages
I expect the output for BillCycle to be the ID of the first record where StageFlag = 'S' for all records up to and including the end stage 'E'. Then the next set will start with the ID starting with 'S' again.
You can assign a group using a cumulative sum and then use a window function to get the value:
select i.*,
max(id) over (partition by project, grp) as invoice_id
from (select i.*,
sum(case when i.stageflag = 'S' then 1 else 0 end) over (partition by i.project order by i.stagedate) as grp
from InvoiceStages i
) i;
If the ids increase along with the date, you can do this without a subquery:
select i.*,
max(case when stageflag = 'S' then id end) over (partition by project) as invoice_id
from invoicestages i;

Need a simple query to calculate sequence length in SQL Server

I have this view that represent the status of connections for each user to a system inside table as below:
---------------------------------------
|id | date | User | Connexion |
|1 | 01/01/2018 | A | 1 |
|2 | 02/01/2018 | A | 0 |
|3 | 03/01/2018 | A | 1 |
|4 | 04/01/2018 | A | 1 |
|5 | 05/01/2018 | A | 0 |
|6 | 06/01/2018 | A | 0 |
|7 | 07/01/2018 | A | 0 |
|8 | 08/01/2018 | A | 1 |
|9 | 09/01/2018 | A | 1 |
|10 | 10/01/2018 | A | 1 |
|11 | 11/01/2018 | A | 1 |
---------------------------------------
The target output would be to get the count of succeeded and failed connection order by date so the output would be like that
---------------------------------------------------------------
|StartDate EndDate User Connexion Length|
|01/01/2018 | 01/01/2018 | A | 1 | 1 |
|02/01/2018 | 02/01/2018 | A | 0 | 1 |
|03/01/2018 | 04/01/2018 | A | 1 | 2 |
|05/01/2018 | 07/01/2018 | A | 0 | 3 |
|08/01/2018 | 11/01/2018 | A | 1 | 4 |
---------------------------------------------------------------
This is what is called a gaps-and-islands problem. The best solution for your version is a difference of row numbers:
select user, min(date), max(date), connexion, count(*) as length
from (select t.*,
row_number() over (partition by user order by date) as seqnum,
row_number() over (partition by user, connexion order by date) as seqnum_uc
from t
) t
group by user, connexion, (seqnum - seqnum_uc);
Why this works is a little tricky to explain. Generally, I find that if you stare at the results of the subquery, you'll see how the difference is constant for the groups that you care about.
Note: You should not use user or date for the names of columns. These are keywords in SQL (of one type or another). If you do use them, you have to clutter up your SQL with escape characters, which just makes the code harder to write, read, and debug.

What is the best way to apply SQL Pivot to a table?

I'm trying to use the pivot function but not sure how to replace the Letters in the bi-weekly table to a persons name instead of the query result. Here is my query.
SELECT a.OCD, a.[f_name],a.[l_name],a.[ads_phone], b.wk1m, b.wk1t, b.wk1w, b.wk1r, b.wk1f, b.wk2m, b.wk2t, b.wk2w, b.wk2r, b.wk2f
FROM [dbo].[tbl_teleworkers] as a
inner join [dbo].[tbl_scheduled] as b ON a.pin = b.pin
where ocd = '022'
here is my result:
OCD|f_name|l_name|ads_phone|wk1m|wk1t|wk1w|wk1r|wk1f|wk2m|wk2t|wk2w|wk2r|wk2f
022|John |smith |111-1111 |M | | | R | | | | | |
022|Jane |smith |222-2222 | | | | | | | | W | |
022|Joe |smith |333-3333 |M | | | | F | | | | |
022|Jim |smith |444-4444 | | T | | | | M | | | |
022|Jill |smith |555-5555 |M | | W | | | | | | R |
Here is what I'm looking to get: So instead of the letters of the week. I'm trying to display the person's name and phone number.
wk1m |wk1t|wk1w|wk1r |wk1f|wk2m|wk2t|wk2w |wk2r|wk2f
John | | |John | | | | | |
phone| | |phone| | | | | |
| | | | | | |Jane S| |
| | | | | | |phone | |
Joe | |
phone| |
Any help would be greatly appreciated.
Thanks!
I'm going to ignore the question in your subject line because your sample data and desired output do not require a PIVOT at all.
You can get your desired output by making each column a CASE expression. In each wk** column, if the value is not empty, return the value of the first name, last initial (if desired) and phone number concatenated together.

How to use ActiveRecord for multiply join same table (ruby on rails)

My application for learning words by reading sentences and translation of these sentences.
Each word has and belongs to many sentences and each sentence has translated sentences ('links' table) but not all translations for specific language (many english sentences are translated into japanese but do not have a translation into Russian)
I need to get words (english for example) that have sentences (english) that have translated sentences (russian)
DB:
words sentences_words sentences links(sentences_sentences)
_______________________ _____________________ __________________ _____________________________
|id |lang |word | |word_id|sentence_id| |id|lang|sentence| |sentence_1_id|sentence_2_id|
|1 |rus |Ё | | 1 | 1 | |1 |rus | ЁЖ | | 1 | 5 |
|2 |rus |Ж | | 1 | 4 | |2 |rus | ЗЖ | | 1 | 8 |
|3 |rus |З | | 2 | 1 | |3 |rus | ЙЫ | | 2 | 6 |
|4 |rus |Й | | 2 | 2 | |4 |rus | ЁЗ | | 3 | 7 |
|5 |rus |Ы | | 3 | 2 | |5 |eng | ab | | 3 | 10 |
|6 |eng |a | | 3 | 4 | |6 |eng | bc | | | |
|7 |eng |b | | 4 | 3 | |7 |eng | ca | | | |
|8 |eng |c | | 5 | 3 | |8 |jpn | | | | |
|9 |jpn | ... | | 6 | 5 | |9 |jpn | | | | |
|10 |jpn | ... | | 6 | 7 | |10|jpn | | | | |
| | | | | 7 | 5 | |11|jpn | | | | |
| | | | | 7 | 6 | |12|jpn | | | | |
| | | | | 8 | 6 | |13|jpn | | | | |
| | | | | 8 | 7 | |14|jpn | | | | |
Models:
class Word < ApplicationRecord
has_and_belongs_to_many :sentences
end
class Sentence < ApplicationRecord
has_and_belongs_to_many :words
has_and_belongs_to_many :translations,
class_name: "Sentence",
join_table: "links",
foreign_key: "sentence_1_id",
association_foreign_key: "sentence_2_id"
end
This sql works nice but I need activerecord query:
sql = "
select w.word from words w
join sentences_words sw on sw.word_id = w.id
join sentences s1 on sw.sentence_id = s1.id
join links l on l.sentence_1_id = s1.id
join sentences s2 on l.sentence_2_id = s2.id
where w.language = 'eng'
and s1.language = 'eng'
and s2.language = 'rus'
group by w.id
order by w.id"
#words = ActiveRecord::Base.connection.execute(sql)
UPD:
This code also works:
#words = Word.joins("INNER JOIN sentences_words sw ON sw.word_id = words.id
INNER JOIN sentences s1 on sw.sentence_id = s1.id
INNER JOIN links l on l.sentence_1_id = s1.id
INNER JOIN sentences s2 on l.sentence_2_id = s2.id
WHERE words.language = 'eng'
AND s1.language = 'eng'
AND s2.language = 'rus'").group(:id).order(:id)
Is it possible to do something like that? (its not works):
#words = Word.where(Sentence.where(language: 'eng').joins(:sentences).
where(sentences: {language: 'rus'})).where(language: 'eng')
or
#words = Word.joins(:sentences).joins(:translations).
where(words: {language: 'eng'}, sentences: {language: 'eng'}, translations: {language: 'rus'}
Thank you!
Hi #Dmitry you can use the nested join for this . Here is a good link for this [http://guides.rubyonrails.org/active_record_querying.html#joins]

Select distinct from multiple columns and its matching values sum

I have this table named Orders.
Each row of the table represents an order made by a customer.
prod means product
+-----------------------------------------------------------------------------------+
| prod_1 | prod_1_qty | prod_2 |prod_2_qty | prod_3 | prod_3_qty |
|-------------------------------------------------------|---------------------------|
| chair | 3 | board |9 | bed |4 |
| board | 8 | door |2 | desk |2 |
| chair | 2 | window |1 | door |6 |
| desk | 4 | chair |3 | sofa |1 |
I would like to write a query that returns the quantity of each product ordered like this:
+---------------------------+
| product | product_qty |
|---------------------------|
| chair | 8 |
| board | 17 |
| door | 8 |
| window | 1 |
| sofa | 1 |
| bed | 4 |
| desk | 6 |
Is there any way to achieve this using T-SQL, and if so, what is the query one would use to do this?
SELECT x.prod
, SUM(x.prod_qty) AS total
FROM (
SELECT prod1 AS prod, prod_qty AS total FROM table
UNION ALL
SELECT prod2 AS prod, prod_qty AS total FROM table
UNION ALL
SELECT prod3 AS prod, prod_qty AS total FROM table
) x
GROUP BY x.prod