Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
0 / 0 / 0
Регистрация: 10.08.2016
Сообщений: 31

UpdateCommand для SELECTa из нескольких таблиц

24.09.2017, 17:14. Показов 2301. Ответов 15

Студворк — интернет-сервис помощи студентам
Нуждаюсь в помощи на понимание C#.
Ткните пожалуйста носом как писать запросы для DataAdaptera если SELECT тянет данные из несколькиз таблиц. Пробовал писать INSERT, DELET и UPDATE команды по аналогии с командами сгенерированными типизированными DataSetами, но успеха не достиг.
Еще в DataGridView вводятся новые данные которые затрагивают только одну таблицу данные из других таблиц не трогаются, то есть по идее изменения должны вноситься INSERTOом, но срабатывает UPDATE.
Объясните как правильно записывать изменения из DataGridView в БД.
Вот селект:
SQL
1
2
3
4
5
6
7
8
9
SELECT street_name AS Улица, 
            house_number AS 'Номер дома', 
            apartment_no AS 'Номер квартиры',
            id AS 'Идентификатор'                  
    FROM apartments      
            INNER JOIN houses
        ON apartments.house_id = houses.house_id 
            INNER JOIN streets
            ON houses.street_id = streets.street_id
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
24.09.2017, 17:14
Ответы с готовыми решениями:

Запрос для нескольких таблиц
Есть две таблицы: vehicles id|user_id 1|1 2|2 3|2 4|3 5|3 user_messages

Один идентификатор для нескольких таблиц
Здравствуйте, я новичок в проектирование БД, поэтому мне нужен совет. Имеется несколько товаров с разной структурой. Допустим телефоны и...

Ключевое поле для нескольких таблиц
Доброго всем времени суток! Разрабатываю приложение с базой данных в C++builder и столкнулся со следующей проблемой: Есть 3 таблицы,...

15
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
24.09.2017, 17:25
Цитата Сообщение от sparkstas Посмотреть сообщение
как писать запросы для DataAdaptera если SELECT тянет данные из несколькиз таблиц.
Создайте обновляемые представления в базе, а в коде работайте с этими представлениями как с обычными таблицами.
0
0 / 0 / 0
Регистрация: 10.08.2016
Сообщений: 31
24.09.2017, 18:08  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
Создайте обновляемые представления в базе, а в коде работайте с этими представлениями как с обычными таблицами.
Возможно мне не совсем подходит это решение. В Гриде я добавляю столбцы для редактирования. В представлении нет возможности получить нужный мне столбец, в итоге всё равно придется писать команды вручную.
0
 Аватар для wm_leviathan
214 / 214 / 73
Регистрация: 12.01.2011
Сообщений: 767
24.09.2017, 18:54
Лучший ответ Сообщение было отмечено sparkstas как решение

Решение

вариант 1:
как сказал kolorotur, через представления. Но в этом случае я бы не стал использовать представления + sql. Зачем их мешать ? Если использовать представления (+LINQ) то EntityFramework, в нем есть все необходимое:
как пример небольшой:
есть 2 таблицы:
TCustomer(покупатель)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public partial class TCustomer
    {
        public TCustomer()
        {
            this.TOrders = new HashSet<TOrders>();
        }
    
        public int id_customer { get; set; }
        public string surname { get; set; }
        public string firstName { get; set; }
        public string lastName { get; set; }
    
        public virtual ICollection<TOrders> TOrders { get; set; }
    }
и свзанная с ней по id TOrders(покупки)
C#
1
2
3
4
5
6
7
8
9
public partial class TOrders
    {
        public int id_order { get; set; }
        public int id_customer { get; set; }
        public string productName { get; set; }
        public Nullable<int> productKol { get; set; }
    
        public virtual TCustomer TCustomer { get; set; }
    }
DaoRecord - вьюха объедененных таблиц TCustomer и TOrders
C#
1
2
3
4
5
6
7
8
9
public  class DaoRecord
    {
        public int id_customer { get; set; }
        public string surname { get; set; }
        public string firstName { get; set; }
        public string lastName { get; set; }
        public string productName { get; set; }
        public Nullable<int> productKol { get; set; }
    }
и контекст:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public partial class TestDbContext : DbContext
    {
        public TestDbContext()
            : base("name=TestDbContext")
        {
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }
    
        public virtual DbSet<TCustomer> TCustomer { get; set; }
        public virtual DbSet<TOrders> TOrders { get; set; }
    }
и собственно класс для отображения\редактирования\добавления\уд аления полей этих таблиц:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
 class DbWorkService : IDbWorkService
    {
        public List<DaoRecord> GetAllRecord()
        {
            try
            {
                using (var context = new TestDbContext())
                {
                    var query = from c in context.TCustomer
                                join o in context.TOrders on c.id_customer equals o.id_customer
                                select new DaoRecord
                                {
                                    id_customer = c.id_customer,
                                    surname     = c.surname,
                                    firstName   = c.firstName,
                                    lastName    = c.lastName,
                                    productName = o.productName,
                                    productKol  = o.productKol
                                };
 
                    return query.ToList();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
                return null;
            }
        }
 
        public bool AddRecord(TCustomer customer, StringBuilder message)
        {
            try
            {
                using (var context = new TestDbContext())
                {
                    context.TCustomer.Add(customer);
                    context.SaveChanges();
                }
                
                message.Append("Добавление записи успешно выполнено. ");
                return true;
            }
            catch (Exception ex)
            {
                message.Append("Ошибка добавления записи. " + ex.Message);
                return false;
            }
        }
 
        public bool EditRecord(TCustomer customer, StringBuilder message)
        {            
            try
            {
                using (var context = new TestDbContext())
                {
                    TCustomer currCustomer = context.TCustomer.Where(c => c.id_customer == customer.id_customer).FirstOrDefault();
                    currCustomer.surname   = customer.surname;
                    currCustomer.firstName = customer.firstName;
                    currCustomer.lastName  = customer.lastName;
                    
                    TOrders currOrder     = context.TOrders.Where(o => o.id_customer == customer.id_customer).FirstOrDefault();
                    currOrder.productName = customer.TOrders.FirstOrDefault().productName;
                    currOrder.productKol  = customer.TOrders.FirstOrDefault().productKol;
 
                    context.SaveChanges();
                }
 
                message.Append("Обновление записи успешно выполнено.");
                return true;
            }
            catch (Exception ex)
            {
                message.Append("Ошибка обновления записи. " + ex.Message);
                return false;
            }
 
        }
 
        public bool DeleteRecord(int id_customer, StringBuilder message)
        {
            try
            {
                using (var context = new TestDbContext())
                {
                    TCustomer currCustomer = context.TCustomer.Where(c => c.id_customer == id_customer).FirstOrDefault();
                    TOrders currOrder      = context.TOrders.Where(o => o.id_customer == id_customer).FirstOrDefault();
 
                    context.TOrders.Remove(currOrder);
                    context.TCustomer.Remove(currCustomer);
                    context.SaveChanges();
                }
 
                message.Append("Удаление записи успешно выполнено.");
                return true;
            }
            catch (Exception ex)
            {
                message.Append("Ошибка удаления записи. " + ex.Message);
                return false;
            }
        }
    }
это что касалось представлений и EF. Кстати сейчас это требуется повсеместно работодателями.
Вариант 2:
Конечно можно и средствами голого SQL но тогда придется использовать транзакции.
Как то делал дипломную человеку было у меня ограничение только SQL (просто представления, EF, и прочее они не проходили).
к примеру таблица TPerson(люди) и ее подчиненная TSize(размеры одежды) UPDATE выглядел так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
public static string updatePerson = "BEGIN TRANSACTION WORK; " +
            "update WorkDb.dbo.TPerson set " +
            "id_subdivision = @id_subdivision, id_profession = @id_profession, id_pol = @id_pol, tabnom = @tabnom, " +
            "surname = @surname, first_name = @first_name, last_name = @last_name, date_post = @date_post, date_perevod = @date_perevod, " +
            "del_state = @del_stateP " +
            "where id_person = @id_person " +
            "update WorkDb.dbo.TSize set " +
            "id_person = @id_person, heightOt = @heightOt, heightDo = @heightDo, size_robeOt = @size_robeOt, size_robeDo = @size_robeDo, " +
            "size_boots = @size_boots, size_headdress = @size_headdress, size_protivogaz = @size_protivogaz, " +
            "size_respirator = @size_respirator, size_rukav = @size_rukav, size_gloves = @size_gloves, del_state = @del_stateS " +
            "where id_size = @id_size " +
            "COMMIT WORK;";
и код
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  public void update()
        {
            var addPerson = helper.GetForm<addPersonForm>();
            SqlCommand commandUpdate = new SqlCommand(Classes.SqlQueryClass.updatePerson);
            commandUpdate.Parameters.Add("@id_subdivision", SqlDbType.Int).Value = addPerson._cbSubdivision.SelectedValue.ToString();
            commandUpdate.Parameters.Add("@id_profession", SqlDbType.Int).Value = addPerson._cbProfession.SelectedValue.ToString();
            commandUpdate.Parameters.Add("@id_pol", SqlDbType.Int).Value = addPerson._cbPol.SelectedValue.ToString();
            commandUpdate.Parameters.Add("@tabnom", SqlDbType.NVarChar).Value = addPerson._txtTabNom.Text;
            commandUpdate.Parameters.Add("@surname", SqlDbType.NVarChar).Value = addPerson._txtSurname.Text;
            commandUpdate.Parameters.Add("@first_name", SqlDbType.NVarChar).Value = addPerson._txtName.Text;
            commandUpdate.Parameters.Add("@last_name", SqlDbType.NVarChar).Value = addPerson._txtLastName.Text;
            commandUpdate.Parameters.Add("@date_post", SqlDbType.DateTime).Value = addPerson._dtpDatePost.Value;
            commandUpdate.Parameters.Add("@date_perevod", SqlDbType.DateTime).Value = addPerson._dtpDatePerevod.Text == " "? DBNull.Value : addPerson._dtpDatePerevod.Value;
            commandUpdate.Parameters.Add("@del_stateP", SqlDbType.Bit).Value = false;
            commandUpdate.Parameters.Add("@id_person", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["id_person"].Value.ToString();
 
            commandUpdate.Parameters.Add("@heightOt", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["heightOt"].Value.ToString() == "" ? DBNull.Value : addPerson._dgvSize.Rows[0].Cells["heightOt"].Value;
            commandUpdate.Parameters.Add("@heightDo", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["heightDo"].Value.ToString() == "" ? DBNull.Value : addPerson._dgvSize.Rows[0].Cells["heightDo"].Value;
            commandUpdate.Parameters.Add("@size_robeOt", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["size_robeOt"].Value.ToString() == "" ? DBNull.Value : addPerson._dgvSize.Rows[0].Cells["size_robeOt"].Value;
            commandUpdate.Parameters.Add("@size_robeDo", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["size_robeDo"].Value.ToString() == "" ? DBNull.Value : addPerson._dgvSize.Rows[0].Cells["size_robeDo"].Value;
            commandUpdate.Parameters.Add("@size_boots", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["size_boots"].Value.ToString() == "" ? DBNull.Value : addPerson._dgvSize.Rows[0].Cells["size_boots"].Value;
            commandUpdate.Parameters.Add("@size_headdress", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["size_headdress"].Value.ToString() == "" ? DBNull.Value : addPerson._dgvSize.Rows[0].Cells["size_headdress"].Value;
            commandUpdate.Parameters.Add("@size_protivogaz", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["size_protivogaz"].Value.ToString() == "" ? DBNull.Value : addPerson._dgvSize.Rows[0].Cells["size_protivogaz"].Value;
            commandUpdate.Parameters.Add("@size_respirator", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["size_respirator"].Value.ToString() == "" ? DBNull.Value : addPerson._dgvSize.Rows[0].Cells["size_respirator"].Value;
            commandUpdate.Parameters.Add("@size_rukav", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["size_rukav"].Value.ToString() == "" ? DBNull.Value : addPerson._dgvSize.Rows[0].Cells["size_rukav"].Value;
            commandUpdate.Parameters.Add("@size_gloves", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["size_gloves"].Value.ToString() == "" ? DBNull.Value : addPerson._dgvSize.Rows[0].Cells["size_gloves"].Value;
            commandUpdate.Parameters.Add("@del_stateS", SqlDbType.Bit).Value = false;
            commandUpdate.Parameters.Add("@id_size", SqlDbType.Int).Value = addPerson._dgvSize.Rows[0].Cells["id_size"].Value.ToString();
 
            if ((bool)workDb.SqlHandler(commandUpdate, false))
            {
                MessageBox.Show("Данные успешно обновлены.", "Внимание", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
 
        }
Конечно не красиво, но что поделать как то заполнять надо было, таблица получилась большая.
и функция в базу:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 public object SqlHandler(SqlCommand cmd, bool modeSelect)
        {
            try
            {
                using (SqlConnection con = new SqlConnection(helper.SqlString()))
                {
                    con.Open();
                    using (SqlDataAdapter dataAdapter = new SqlDataAdapter(cmd))
                    {
                        dataAdapter.SelectCommand.Connection = con;
                        dataAdapter.SelectCommand = cmd;
                        DataTable table = new DataTable();
                        table.Locale = System.Globalization.CultureInfo.InvariantCulture;
                        dataAdapter.Fill(table);
                        if (modeSelect)
                            return table;
                        else
                            return true;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Ошибка при выполнении запроса в базу. " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                if (modeSelect)
                    return null;
                else
                    return false;
            }
        }
1
0 / 0 / 0
Регистрация: 10.08.2016
Сообщений: 31
24.09.2017, 18:55  [ТС]
В DataGridView у меня получается вот такая таблица:

В поле Показания заносятся данные после чего их нужно сохранить.
В БД даныые заносятся в таблицу indications в поля apartment_id и indication. Т. е. запрос должен быть такой:
SQL
1
INSERT INTO indication (apartment_id, indication) VALUES (values1, values2)
Я в коде по аналогии с запросами созданными в конструкторе создал вот такие команды:
C#
1
2
3
4
5
6
7
8
9
10
11
12
da.InsertCommand = new SqlCommand("INSERT INTO indications (apartment_id, indication) VALUES(@Идентификатор, @Показания)", connection);
                    da.DeleteCommand = new SqlCommand(@"DELETE FROM indications
WHERE(operation_id = @Original_operation_id) AND(@IsNull_apartment_id = 1) AND(apartment_id IS NULL) AND(date_operation = @Original_Дата) AND(@IsNull_Показания = 1) AND(indication IS NULL) OR
                         (operation_id = @Original_operation_id) AND(apartment_id = @Original_apartment_id) AND(date_operation = @Original_Дата) AND(@IsNull_Показания = 1) AND(indication IS NULL) OR
                         (operation_id = @Original_operation_id) AND(@IsNull_apartment_id = 1) AND(apartment_id IS NULL) AND(date_operation = @Original_Дата) AND(indication = @Original_Показания) OR
                         (operation_id = @Original_operation_id) AND(apartment_id = @Original_apartment_id) AND(date_operation = @Original_Дата) AND(indication = @Original_Показания)", connection);
                    da.UpdateCommand = new SqlCommand(@"UPDATE       indications
SET                apartment_id = @Идентификатор, indication = @Показания
WHERE(@IsNull_Идентификатор = 1) AND(apartment_id IS NULL) AND(@IsNull_Показания = 1) AND(indication IS NULL) OR
                         (apartment_id = @Original_Идентификатор) AND(@IsNull_Показания = 1) AND(indication IS NULL) OR
                         (@IsNull_Идентификатор = 1) AND(apartment_id IS NULL) AND(indication = @Original_Показания) OR
                         (apartment_id = @Original_Идентификатор) AND(indication = @Original_Показания)", connection);
Но при попытке сохранить вылетает эксепшн:
Необработанное исключение типа "System.Data.SqlClient.SqlException" в System.Data.dll
Дополнительные сведения: Необходимо объявить скалярную переменную "@Идентификатор".
0
0 / 0 / 0
Регистрация: 10.08.2016
Сообщений: 31
24.09.2017, 19:29  [ТС]
Цитата Сообщение от wm_leviathan Посмотреть сообщение
Если использовать представления (+LINQ) то EntityFramework
С EF не работал и в вашем коде мало что понимаю, знаний не хватает.

Добавлено через 10 минут
Цитата Сообщение от wm_leviathan Посмотреть сообщение
commandUpdate.Parameters.Add
Похоже мне нужно таким же образом объявить параметры для своего адаптера?
А что присвоить параметру?
0
 Аватар для wm_leviathan
214 / 214 / 73
Регистрация: 12.01.2011
Сообщений: 767
24.09.2017, 19:39
Цитата Сообщение от sparkstas Посмотреть сообщение
А что присвоить параметру?
Данные которые будете обновлять.
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,230
24.09.2017, 19:55
Как то у вас не по фэн-шую сделано: при выборке набор данных формируется из 3-таблиц, однако в гриде есть столбец, данные для которого вставляются вообще в 4 таблицу.
Как уже сказали, создайте view на основе 4-х таблиц работайте с этой view.

Добавлено через 10 минут
Вроде вот так будет выглядеть запрос:
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
IF object_id('vIndications') IS NOT NULL    DROP VIEW vIndications;
 
CREATE VIEW vIndications AS
SELECT street_name AS StreetName, 
            house_number AS HouseNumber, 
            apartment_no AS ApartmentNumber,
            id AS ApartmentId,
            indications.indication AS Indication                   
    FROM apartments AS ap
            INNER JOIN houses
        ON apartments.house_id = houses.house_id 
            INNER JOIN streets
            ON houses.street_id = streets.street_id
            INNER JOIN indications 
            ON indications.apartment_id = apartments.id
1
0 / 0 / 0
Регистрация: 10.08.2016
Сообщений: 31
24.09.2017, 19:58  [ТС]
Цитата Сообщение от sparkstas Посмотреть сообщение
Похоже мне нужно таким же образом объявить параметры для своего адаптера?
Параметры объявил, но делу это не помогло, потому что адаптер пытается обновить строки которые не существуют, что естественно вызывает исключение, так как строки нужно вставлять новые. Для меня тупик, что делать в такой ситуации.

Цитата Сообщение от IamRain Посмотреть сообщение
Как то у вас не по фэн-шую сделано: при выборке набор данных формируется из 3-таблиц,
однако в гриде есть столбец, данные для которого
Как мне тогда сделать, из трех таблиц для наглядного отображения, чтоб пользователь видел, что он редактирует, а не набор id, которые непонятно к чему относятся.
Я бы рад работать с представлением, если подскажете, как мне в представлении организовать колонку с пустыми строками.
Задача такая, есть таблица со списком квартир и таблица с показаниями, нужно для каждой квартиры внести показания.
Как это лучше всего организовать.

Добавлено через 2 минуты
Цитата Сообщение от IamRain Посмотреть сообщение
Вроде вот так будет выглядеть запрос:
Этот запрос выведет таблицу с уже существующими показаниями. А мне нужно вносить новые, а не редактировать старые.
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,230
24.09.2017, 20:04
Цитата Сообщение от sparkstas Посмотреть сообщение
а не набор id
Какой набор id? У вас набор данных возвращает следующие колонки, взятые из 4 таблиц: StreetName, HouseNumber, ApartmentNumber, ApartmentId, Indication.
А на гриде вы можете назвать колонки уже более удобными для пользователя именами, либо скрыть ненужные.

Добавлено через 1 минуту
Цитата Сообщение от sparkstas Посмотреть сообщение
А мне нужно вносить новые, а не редактировать старые.
Вы будете обновлять одну View, обновление которой будет сопровождаться вставкой данных в нужные вам таблицы, насколько я знаю; где вы сможете и вносить новые данные, и редактировать старые.
0
360 / 287 / 76
Регистрация: 21.06.2016
Сообщений: 1,115
24.09.2017, 20:24
sparkstas, если работаете с ms sql, то можно попробовать работать с xml данными, и не заморачиваться с адаптером. К тому же при использовании внешних ключей основанных на identity, тяжело будет делать insert более 1-ой записи в разные таблицы. Для упрощения я бы советовал временные таблицы, используя функционал OUTPUT(INSERTED). По скорости можно проиграть, но по простоте выиграть, поскольку EFВы не используете.
1
0 / 0 / 0
Регистрация: 10.08.2016
Сообщений: 31
24.09.2017, 20:29  [ТС]
Цитата Сообщение от IamRain Посмотреть сообщение
Вы будете обновлять одну View,
Видимо я чего-то не понимаю. Мне нужно получить таблицу с четырьмя полями: street_name, house_number, apartment_number, indication. Где первые три должны быть заполнены из соответствующих табли, а четвертая содержать пустые строки. Как мне получить такое представление?
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,230
24.09.2017, 20:37
Цитата Сообщение от sparkstas Посмотреть сообщение
Видимо я чего-то не понимаю. Мне нужно получить таблицу с четырьмя полями: street_name, house_number, apartment_number, indication. Где первые три должны быть заполнены из соответствующих табли, а четвертая содержать пустые строки
Можно попробовать сделать left outer join и посмотреть что получится:
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE VIEW vIndications AS
SELECT street_name AS StreetName, 
            house_number AS HouseNumber, 
            apartment_no AS ApartmentNumber,
            id AS ApartmentId,
            indications.indication AS Indication                   
    FROM apartments AS ap
            INNER JOIN houses
        ON apartments.house_id = houses.house_id 
            INNER JOIN streets
            ON houses.street_id = streets.street_id
            LEFT JOIN indications 
            ON indications.apartment_id = apartments.id
Теперь, если при формировании набора данных показания в какую-либо квартиру не отправлялись, то в соответствующей строке в колонке Indication у вас будет Null.
Btw, можно не указывать ключевое слово INNER в запросе, поскольку в TSQL INNER JOIN является JOIN-ом по-умолчанию.
0
0 / 0 / 0
Регистрация: 10.08.2016
Сообщений: 31
24.09.2017, 20:53  [ТС]
Цитата Сообщение от IamRain Посмотреть сообщение
Можно попробовать сделать left outer join и посмотреть что получится:
Показания вносятся каждый месяц для каждой квартиры, поэтому join тут не подходит.

Добавлено через 10 минут
Цитата Сообщение от hoolygan Посмотреть сообщение
я бы советовал временные таблицы
Видимо так и придется поступить, либо сохранять изменения проходясь по гриду циклом.
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,230
24.09.2017, 20:56
Как вариант, можно вместо вьюхи написать процедуру, которая принимает дату (месяц и год), и возвращат набор данных, отфильтрованный по месяцу и году. Если в таблице Indication есть колонка с датой (месяц и год), а она там должна быть логически, то добавляете проверку в условие on последнего join-а.
0
0 / 0 / 0
Регистрация: 10.08.2016
Сообщений: 31
24.09.2017, 21:00  [ТС]
Цитата Сообщение от IamRain Посмотреть сообщение
можно вместо вьюхи написать процедуру, которая принимает дату (месяц и год)
Можно попробовать. Спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
24.09.2017, 21:00
Помогаю со студенческими работами здесь

Создание таблиц для нескольких пользователей
Здравствуйте. Извиняюсь, если такая тема уже существует. Пишу сайт, в нём должно быть несколько видов пользователей (юридические и...

Уникальный индекс для нескольких таблиц
Добрый день, Подскажите, пожалуйста, как лучше решить такую задачу: В базе есть несколько одинаковых по структуре таблиц, в каждой...

Стили для нескольких таблиц на странице
Подскажите, пожалуйста, можно ли добиться кроссплатформенности? Нормальное отображение только в хромовых браузерах. В остальных все...

Форма, для заполнения нескольких таблиц
Друзья, для начала хочу поблагодарить за прошлые уроки, что вы мне охотно подсказали. Я хорошо разобрался в структуре базы, но передо мной...

MySQL запрос для нескольких таблиц!
Здравствуйте! У меня такая проблема: &lt;?php if (isset ($_GET)) {$id = $_GET; } $result = mysql_query(&quot;SELECT * FROM ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru